home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Plus 2004 #11
/
Amiga Plus CD - 2004 - No. 11.iso
/
AmiSoft
/
Game
/
board
/
Saga.lha
/
Saga
/
source
/
system.c
< prev
Wrap
C/C++ Source or Header
|
2004-09-01
|
179KB
|
4,207 lines
/* Known bugs:
memory leak in createcounters()/destroycounters(), not sure why.
1. INCLUDES ----------------------------------------------------------- */
#include <exec/exec.h>
#include <intuition/intuition.h>
#include <utility/tagitem.h>
#include <graphics/gfx.h>
#include <libraries/gadtools.h> // struct NewMenu
#include <devices/timer.h> // struct timeval
#include <dos/dosextens.h> // struct Process
#include <libraries/asl.h> // ASL_FileRequest
#include <dos/dostags.h> // SYS_Output
#include <dos/datetime.h> // struct DateTime
#include <libraries/locale.h>
#define OLD_GRAPHICS_GFXMACROS_H
#include <graphics/gfxmacros.h>
#include <hardware/custom.h>
#include <hardware/dmabits.h>
#include <ctype.h> // toupper()
#include <stdlib.h> /* EXIT_SUCCESS, etc. */
#include <stdio.h>
#include <string.h> // strcpy(), etc.
#define ASSERT
#include <assert.h>
#include "saga.h"
#define CATCOMP_NUMBERS
#define CATCOMP_CODE
#define CATCOMP_BLOCK
#include <clib/exec_protos.h> // OpenLibrary(), etc.
#include <clib/intuition_protos.h> // Object, etc.
#include <clib/graphics_protos.h>
#include <clib/dos_protos.h>
#include <clib/gadtools_protos.h>
#include <clib/timer_protos.h>
#include <clib/locale_protos.h> // GetCatalogStr()
#include <clib/asl_protos.h>
#include <clib/diskfont_protos.h>
#include "saga_strings.h"
// #define ASSERT
// 2. DEFINES ------------------------------------------------------------
#define QUICKMOVES
// #define EXTRAVERBOSE
// version-dependent constants
#define TITLEBAR "Saga 1.5"
#define VERSION "$VER: Saga 1.5 (2.9.2004)"
#define RELEASEDATE "02-Sep-04"
#define COPYRIGHT "© 2002-2004 Amigan Software"
#define CONFIGLENGTH 23
#define SAVELENGTH 577
#define SCOREDISTANCE 13
#define MESSAGEY (TBSIZE + 473)
#define ONE_BILLION 1000000000
// scancodes
#define SCAN_Q 16
#define ESCAPE 69
#define SCAN_RIGHT 78
#define SCAN_LEFT 79
#define SCAN_F1 80
#define SCAN_F2 81
#define SCAN_F3 82
#define SCAN_F4 83
#define SCAN_F5 84
#define SCAN_F6 85
#define HELP 95
#define FIRSTQUALIFIER 96
#define LASTQUALIFIER 103
#define KEYUP 128 /* key release */
#define HERO_STRENGTH 5
#define HERO_MOVES 4
STRPTR trueheroname[HEROES + 1] =
{ "Beowulf",
"Brunhild",
"Egil",
"Ragnar",
"Siegfried",
"Starkad"
}, cycleheroname[HEROES + 1] =
{ " Beowulf:",
" Brunhild:",
" Egil:",
" Ragnar:",
"Siegfried:",
" Starkad:"
};
#define MN_PROJECT 0
#define MN_SETTINGS 1
#define MN_HELP 2
#define IN_NEW 0
#define IN_OPEN 1
#define IN_SAVE 3
#define IN_SAVEAS 4
#define IN_QUIT 6
#define IN_SHOW_TITLEBAR 0
#define IN_GAME_SUMMARY 0
#define IN_HELP_1 2
#define IN_HELP_2 3
#define IN_HELP_3 4
#define IN_HELP_4 5
#define IN_ABOUT 7
#define INDEX_PROJECT 0
#define INDEX_NEW 1
#define INDEX_OPEN 2
#define INDEX_SAVE 4
#define INDEX_SAVE_AS 5
#define INDEX_QUIT 7
#define INDEX_SETTINGS 8
#define INDEX_SHOW_TITLEBAR 9
#define INDEX_HELP 10
#define INDEX_GAME_SUMMARY 11
#define INDEX_HELP_1 13
#define INDEX_HELP_2 14
#define INDEX_HELP_3 15
#define INDEX_HELP_4 16
#define INDEX_ABOUT 18
#define SUMMARYWIDTH 378
#define SUMMARYHEIGHT 42 // +10 per extra line (heading is already factored in)
#define ABOUTLINES 3
#define MENUENTRIES 19 // counting from 0
// 3. EXPORTED VARIABLES -------------------------------------------------
EXPORT struct GfxBase* GfxBase = NULL;
EXPORT struct GadToolsBase* GadToolsBase = NULL;
EXPORT struct IntuitionBase* IntuitionBase = NULL;
EXPORT struct LocaleBase* LocaleBase = NULL;
EXPORT struct Library* TimerBase = NULL;
EXPORT struct ASLBase* ASLBase = NULL;
EXPORT struct DiskFontBase* DiskFontBase = NULL;
EXPORT STRPTR monstertypes[8];
EXPORT SLONG faxirides,
monsters,
treasures;
EXPORT TEXT onekey[ONEKEYS + 1] = {'Y', 'N', 'W', 'R', 'T', 'G', 'L'};
EXPORT UWORD DisplayDepth = DEPTH;
EXPORT TEXT saystring[256 + 1],
saystring2[256 + 1],
numberstring[13 + 1],
label[17 + 1][40 + 1],
line[2][MAXLINES + 1][80 + 1];
EXPORT FLAG advanced = TRUE;
EXPORT ULONG DisplayWidth = SCREENXPIXEL,
DisplayHeight = SCREENYPIXEL;
EXPORT struct Window *MainWindowPtr = NULL,
*HelpWindowPtr = NULL,
*InfoWindowPtr = NULL;
EXPORT struct LocaleInfo li;
EXPORT struct Screen* ScreenPtr = NULL;
EXPORT struct ScreenBuffer* ScreenBuf[2] = {NULL, NULL};
// 4. IMPORTED VARIABLES -------------------------------------------------
IMPORT struct ExecBase* SysBase;
IMPORT struct Custom custom;
IMPORT struct WorldStruct world[36 + 30];
IMPORT struct RuneStruct rune[RUNES + 1];
IMPORT struct TreasureStruct treasure[TREASURES + 1];
IMPORT struct HeroStruct hero[HEROES + 1];
IMPORT struct JarlStruct jarl[JARLS + 1];
IMPORT struct SordStruct sord[SORDS + 1];
IMPORT struct MonsterStruct monster[MONSTERS + 1];
// 5. MODULE VARIABLES ---------------------------------------------------
MODULE STRPTR CycleOptions[4];
MODULE WORD speed = 4;
MODULE UBYTE IOBuffer[600];
MODULE APTR OldWindowPtr = NULL;
MODULE SLONG turn;
MODULE FLAG aga = FALSE,
dbuf = FALSE,
cliload = FALSE,
nodbuf = FALSE,
saveconfig = FALSE,
titlebar = TRUE,
gameover,
loaded;
MODULE TEXT abouttitle[80 + 1],
titlestring[80 + 1],
pathname[256 + 1];
MODULE ULONG DisplayID = HIRES_KEY | PAL_MONITOR_ID | LACE;
MODULE struct RDArgs* ArgsPtr = NULL;
MODULE struct FileRequester* ASLRqPtr = NULL;
MODULE struct Process* ProcessPtr = NULL;
MODULE struct Menu* MenuPtr = NULL;
MODULE struct VisualInfo* VisualInfoPtr = NULL;
MODULE struct TextFont* FontPtr = NULL;
MODULE struct Gadget *SpeedGadgetPtr = NULL,
*CycleGadgetPtr[HEROES + 1] = {NULL, NULL, NULL, NULL, NULL, NULL},
*AdvancedGadgetPtr = NULL,
*GListPtr = NULL,
*PrevGadgetPtr = NULL;
MODULE SLONG tickspeed[6 + 1] = {2, 4, 8, 12, 16, 20, -1};
// 6. MODULE STRUCTURES --------------------------------------------------
MODULE struct
{ UBYTE red, green, blue;
} taxcolours[10 + 1] =
{ { 0, 5, 0 }, // tax 0 (unused)
{ 1, 6, 1 }, // tax 1 (unused)
{ 2, 7, 2 }, // tax 2
{ 3, 8, 3 }, // tax 3
{ 4, 9, 4 }, // tax 4
{ 5, 10, 5 }, // tax 5
{ 6, 11, 6 }, // tax 6
{ 7, 12, 7 }, // tax 7
{ 8, 13, 8 }, // tax 8
{ 9, 14, 9 }, // tax 9
{ 10, 15, 10 } // tax 10
};
MODULE struct
{ WORD x, y;
TEXT text[80 + 1];
} about[ABOUTLINES + 1] =
{ {65, 14},
{65, 24},
{65, 44},
{65, 54}
};
MODULE struct NewMenu NewMenu[MENUENTRIES + 1] =
{ { NM_TITLE, "", 0 , 0, 0, 0}, // 0
{ NM_ITEM, "", "" , 0, 0, 0}, // 1
{ NM_ITEM, "", "" , 0, 0, 0}, // 2
{ NM_ITEM, NM_BARLABEL, 0 , 0, 0, 0}, // 3
{ NM_ITEM, "", "" , 0, 0, 0}, // 4
{ NM_ITEM, "", "" , 0, 0, 0}, // 5
{ NM_ITEM, NM_BARLABEL, 0 , 0, 0, 0}, // 6
{ NM_ITEM, "", "" , 0, 0, 0}, // 7
{ NM_TITLE, "", 0 , 0, 0, 0}, // 8
{ NM_ITEM, "", "", CHECKIT | MENUTOGGLE, 0, 0}, // 9
{ NM_TITLE, "", 0 , 0, 0, 0}, // 10
{ NM_ITEM, "", "" , 0, 0, 0}, // 11 (game summary)
{ NM_ITEM, NM_BARLABEL, 0 , 0, 0, 0}, // 12 (------------)
{ NM_ITEM, "", "1", 0, 0, 0}, // 13 (help 1)
{ NM_ITEM, "", "2", 0, 0, 0}, // 14 (help 2)
{ NM_ITEM, "", "3", 0, 0, 0}, // 15 (help 3)
{ NM_ITEM, "", "4", 0, 0, 0}, // 16 (help 4)
{ NM_ITEM, NM_BARLABEL, 0 , 0, 0, 0}, // 17 (------------)
{ NM_ITEM, "", "?", 0, 0, 0}, // 18 (about)
{ NM_END, NULL, 0 , 0, 0, 0} // 19
};
// These are better to not be allocated on the stack
MODULE ULONG table1[] = {(8L << 16) + 0,
0x00000000, 0x00000000, 0x00000000, // 0 (BLACK)
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, // 1 (WHITE)
0xCCCCCCCC, 0xCCCCCCCC, 0xCCCCCCCC, // 2 (LIGHTGREY)
0x99999999, 0x99999999, 0x99999999, // 3 (MEDIUMGREY)
0x66666666, 0x66666666, 0x66666666, // 4 (DARKGREY)
0x66666666, 0xFFFFFFFF, 0x66666666, // 5 (GREEN)
0x88888888, 0x88888888, 0xFFFFFFFF, // 6 (BLUE)
0x00000000, 0x00000000, 0x00000000, // 7
0};
MODULE ULONG table2[] = {(68L << 16) + 74,
0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, // 74
0xFFFFFFFF, 0xCCCCCCCC, 0x00000000, // 75
0xFFFFFFFF, 0x99999999, 0x00000000, // 76
0xFFFFFFFF, 0x66666666, 0x00000000, // 77
0xFFFFFFFF, 0x33333333, 0x00000000, // 78
0xFFFFFFFF, 0x00000000, 0x00000000, // 79
0x00000000, 0x00000000, 0x00000000, // 80
0x00000000, 0x00000000, 0x99999999, // 81
0x00000000, 0x00000000, 0x00000000, // 82
0x00000000, 0x00000000, 0x99999999, // 83
0x00000000, 0x00000000, 0x00000000, // 84
0x00000000, 0x00000000, 0x99999999, // 85
0xFFFFFFFF, 0xBBBBBBBB, 0x33333333, // 86 (ORANGE)
0xFFFFFFFF, 0x88888888, 0xFFFFFFFF, // 87 (PURPLE)
0xFFFFFFFF, 0x55555555, 0x55555555, // 88 (RED)
0x00000000, 0x00000000, 0x00000000, // 89
0x00000000, 0x00000000, 0x00000000, // 90
0x00000000, 0x00000000, 0x00000000, // 91
0x00000000, 0x00000000, 0xFFFFFFFF, // 92
0x00000000, 0x00000000, 0xFFFFFFFF, // 93
0x10101010, 0x14141414, 0xFFFFFFFF, // 94
0x1F1F1F1F, 0x23232323, 0xFFFFFFFF, // 95
0x2E2E2E2E, 0x32323232, 0xFFFFFFFF, // 96
0x3D3D3D3D, 0x41414141, 0xFFFFFFFF, // 97
0x4C4C4C4C, 0x4F4F4F4F, 0xFFFFFFFF, // 98
0x5B5B5B5B, 0x5E5E5E5E, 0xFFFFFFFF, // 99
0x6A6A6A6A, 0x6D6D6D6D, 0xFFFFFFFF, // 100
0x79797979, 0x7C7C7C7C, 0xFFFFFFFF, // 101
0x87878787, 0x89898989, 0xFFFFFFFF, // 102
0x96969696, 0x98989898, 0xFFFFFFFF, // 103
0xA5A5A5A5, 0xA7A7A7A7, 0xFFFFFFFF, // 104
0xB4B4B4B4, 0xB6B6B6B6, 0xFFFFFFFF, // 105
0xC3C3C3C3, 0xC4C4C4C4, 0xFFFFFFFF, // 106
0xD2D2D2D2, 0xD3D3D3D3, 0xFFFFFFFF, // 107
0xE1E1E1E1, 0xE2E2E2E2, 0xFFFFFFFF, // 108
0xF0F0F0F0, 0xF1F1F1F1, 0xFFFFFFFF, // 109
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, // 110
0x00000000, 0x00000000, 0xFFFFFFFF, // 111
0x00000000, 0x88888888, 0xFFFFFFFF, // 112
0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, // 113
0x99999999, 0x99999999, 0xFFFFFFFF, // 114
0x00000000, 0x00000000, 0x00000000, // 115
0x99999999, 0xFFFFFFFF, 0x99999999, // 116
0x00000000, 0x00000000, 0x00000000, // 117
0xFFFFFFFF, 0xCCCCCCCC, 0x99999999, // 118
0x00000000, 0x00000000, 0x00000000, // 119
0xFFFFFFFF, 0x99999999, 0xFFFFFFFF, // 120
0x00000000, 0x00000000, 0x00000000, // 121
0xFFFFFFFF, 0xFFFFFFFF, 0x99999999, // 122
0x00000000, 0x00000000, 0x00000000, // 123
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, // 124
0x00000000, 0x00000000, 0x00000000, // 125
0xFFFFFFFF, 0x00000000, 0x00000000, // 126 (boing red)
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, // 127 (boing white)
0x44444444, 0x44444444, 0x44444444, // 128
0xAAAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA, // 129
0x66666666, 0x66666666, 0x66666666, // 130
0x77777777, 0x77777777, 0x77777777, // 131
0x88888888, 0x88888888, 0x88888888, // 132
0x99999999, 0x99999999, 0x99999999, // 133
0x55555555, 0x55555555, 0x55555555, // 134
0xBBBBBBBB, 0xBBBBBBBB, 0xBBBBBBBB, // 135
0xFFFFFFFF, 0xCCCCCCCC, 0x66666666, // 136 (Beowulf - orange)
0xFFFFFFFF, 0x66666666, 0x66666666, // 137 (Brunhild - red)
0xFFFFFFFF, 0xFFFFFFFF, 0x33333333, // 138 (Egil - yellow)
0x66666666, 0xFFFFFFFF, 0xFFFFFFFF, // 139 (Ragnar - cyan)
0xAAAAAAAA, 0xAAAAAAAA, 0xFFFFFFFF, // 140 (Siegfried - light blue)
0xFFFFFFFF, 0x66666666, 0xFFFFFFFF, // 141 (Starkad - purple)
0};
MODULE struct NewGadget SpeedGadget =
{ 300, TBSIZE + 296,
128, 13,
"",
NULL,
NULL,
NULL,
NULL,
NULL
}, AdvancedGadget =
{ 300, TBSIZE + 320,
0, 0,
"",
NULL,
NULL,
NULL,
NULL,
NULL
}, CycleGadget[HEROES + 1] = {
{ 300, TBSIZE + 200,
128, 13,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
},
{ 300, TBSIZE + 213,
128, 13,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
},
{ 300, TBSIZE + 226,
128, 13,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
},
{ 300, TBSIZE + 239,
128, 13,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
},
{ 300, TBSIZE + 252,
128, 13,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
},
{ 300, TBSIZE + 265,
128, 13,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
}
};
MODULE SLONG cycleheropos[HEROES + 1] =
{ 2,
3,
5,
3,
0,
3
};
MODULE struct
{ UBYTE red, green, blue;
} herocolour[HEROES + 1] =
{ { 15, 12, 6}, // orange
{ 15, 6, 6}, // red
{ 15, 15, 3}, // yellow
{ 6, 15, 15}, // cyan
{ 10, 10, 15}, // light blue
{ 15, 6, 15} // purple
};
// 7. MODULE FUNCTIONS ---------------------------------------------------
MODULE void gameloop(void);
MODULE void newgame(void);
MODULE void clearkybd(void);
MODULE void titlescreen(void);
MODULE void helpabout(void);
MODULE void resettime(void);
MODULE FLAG loadgame(FLAG aslwindow);
MODULE void savegame(FLAG saveas);
MODULE SLONG checkcountry(WORD mousex, WORD mousey);
MODULE void infowindow(SLONG countertype, SLONG whichcounter);
MODULE void flash(SLONG country);
MODULE void summarywindow(void);
MODULE void cycle(SLONG whichhero, UWORD qual);
MODULE void docwindow(SLONG number);
MODULE void infoloop(void);
// 8. CODE ---------------------------------------------------------------
int main(int argc, char** argv)
{ struct DisplayInfo QueryInfo;
struct TextAttr WormWars8 =
{ (STRPTR) "WormWars.font", 8, FS_NORMAL, FPF_DISKFONT | FPF_DESIGNED
}, Topaz8 =
{ (STRPTR) "topaz.font", 8, FS_NORMAL, FPF_ROMFONT | FPF_DESIGNED
};
struct DateTime DateTime;
struct ScreenModeRequester* smr;
BPTR FileHandle /* = NULL */ ;
FLAG ok;
TEXT datestring[LEN_DATSTRING],
weekdaystring[LEN_DATSTRING],
tempstring[1 + 1],
smrstring[80 + 1],
supergels[2];
SLONG whichcountry, whichhero,
args[7 + 1] = {0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L};
ULONG fonttag,
publictag;
UWORD Pens[13] =
{ BLACK, /* DETAILPEN text in title bar */
WHITE, /* BLOCKPEN fill title bar */
BLACK, /* TEXTPEN regular text on BACKGROUNDPEN */
LIGHTGREY, /* SHINEPEN bright edge */
DARKGREY, /* SHADOWPEN dark edge */
BLUE, /* FILLPEN filling active window borders
and selected gadgets */
BLACK, /* FILLTEXTPEN text rendered over FILLPEN */
MEDIUMGREY,/* BACKGROUNDPEN background colour */
ORANGE, /* HIGHLIGHTTEXTPEN highlighted text on BACKGROUNDPEN
and used against BLOCKPEN in ASL
save requesters */
BLACK, /* BARDETAILPEN text/detail in screen-bar/menus */
WHITE, /* BARBLOCKPEN screen-bar/menus fill */
BLACK, /* BARTRIMPEN trim under screen-bar */
(UWORD) ~0 /* and used against BLOCKPEN in ASL save requesters */
};
/* Colour allocations are as follows:
colours 0-6 are used by the game itself.
colour 7 is the black of the map.
colours 8-43 are map land colours, except that
colours 17-19 are mouse pointer colours.
colours 44-73 are map sea colours.
colours 74-79 are used for the Amigan Software logo.
colour 80 is Scandian coastline.
colour 81 is Scandian sea.
colour 82 is Pictish coastline.
colour 83 is Pictish sea.
colour 84 is Hebridean coastline.
colour 85 is Hebridean sea.
colours 86-88 are used by the game itself.
colour 89 is Suder Gotland land (replacement for colour 17).
colour 90 is Juteland land (replacement for colour 18).
colour 91 is Scandian land (replacement for colour 19).
colour 92 is used for the Amigan Software logo.
colours 93-110 are used for the Saga logo.
colours 111-113 are used for the Amigan Software logo.
colours 114-125 are used for counter colours:
114/115: heroes
116/117: jarls
118/119: monsters
120/121: swords
122/123: treasures
124/125: selected counters
colours 126-127 are colours for the chequered boing ball animation.
colours 128-135 are for the background.
colours 136-141 are hero colours.
Start of program.
version embedding into executable */
if (0) /* that is, never */
{ Printf("%s\n", VERSION);
}
// It would be good to seed the random number generator with the time.
// before the first possible point of failure
init_counters();
for (whichcountry = 0; whichcountry <= 65; whichcountry++)
{ world[whichcountry].hero = -1;
}
pathname[0] = 0;
if (!(IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library", 39L)))
{ strcpy(saystring, "Saga: Can't open intuition.library V39+!)\n");
Write(Output(), saystring, strlen(saystring));
cleanexit(EXIT_FAILURE);
}
ProcessPtr = (struct Process *) FindTask(NULL);
if (SysBase->LibNode.lib_Version < 36L)
{ DisplayAlert(AT_Recovery, "\0\20\20Saga: Can't open exec.library V36+!\0", 24);
cleanexit(EXIT_FAILURE);
}
// From this point onwards, we can be sure we have Kickstart 2.0+...
if (GetVar("cybergfx/supergels", supergels, 2, NULL) == 1)
{ if (supergels[0] == '1')
{ Printf("Saga: ENV:cybergfx/supergels must be cleared to 0 before playing!\n");
cleanexit(EXIT_FAILURE);
} }
/* NOTE FOR TRANSLATORS:
MSG_CHAR_FOO messages are single-character strings which are the
first letter of the relevant word. MSG_UNCHAR_FOO messages are the
rest of the word. Eg. in English, MSG_CHAR_GLORY is "G" and
MSG_UNCHAR_GLORY is "lory". They must each be different among their
'set' (yes/no, glory/luck, restart/transfer/withdraw). */
li.li_Catalog = NULL;
if (LocaleBase = (struct LocaleBase *) OpenLibrary("locale.library", 38))
{ li.li_LocaleBase = LocaleBase;
li.li_Catalog = OpenCatalog(NULL, "Saga.catalog", TAG_DONE);
}
strcpy(tempstring, GetCatalogStr(li.li_Catalog, MSG_CHAR_YES, "Y"));
onekey[ONEKEY_YES] = tempstring[0];
strcpy(tempstring, GetCatalogStr(li.li_Catalog, MSG_CHAR_NO, "N"));
onekey[ONEKEY_NO] = tempstring[0];
strcpy(tempstring, GetCatalogStr(li.li_Catalog, MSG_CHAR_WITHDRAW, "W"));
onekey[ONEKEY_WITHDRAW] = tempstring[0];
strcpy(tempstring, GetCatalogStr(li.li_Catalog, MSG_CHAR_RESTART, "R"));
onekey[ONEKEY_RESTART] = tempstring[0];
strcpy(tempstring, GetCatalogStr(li.li_Catalog, MSG_CHAR_TRANSFER, "T"));
onekey[ONEKEY_TRANSFER] = tempstring[0];
strcpy(tempstring, GetCatalogStr(li.li_Catalog, MSG_CHAR_GLORY, "G"));
onekey[ONEKEY_GLORY] = tempstring[0];
strcpy(tempstring, GetCatalogStr(li.li_Catalog, MSG_CHAR_LUCK, "L"));
onekey[ONEKEY_LUCK] = tempstring[0];
CycleOptions[0] = GetCatalogStr(li.li_Catalog, MSG_GADGET_NONE, "None");
CycleOptions[1] = GetCatalogStr(li.li_Catalog, MSG_HUMAN, "Human");
CycleOptions[2] = "Amiga";
CycleOptions[3] = NULL;
strcpy(abouttitle, GetCatalogStr(li.li_Catalog, MSG_ABOUT, "About"));
strcat(abouttitle, " Saga");
strcpy(about[0].text, TITLEBAR);
about[1].text[0] = 0;
DateTime.dat_Format = FORMAT_DOS;
DateTime.dat_Flags = NULL;
DateTime.dat_StrDate = RELEASEDATE;
DateTime.dat_StrDay = NULL;
DateTime.dat_StrTime = NULL;
DateTime.dat_Stamp.ds_Minute = 0;
DateTime.dat_Stamp.ds_Tick = 0;
if (StrToDate(&DateTime))
{ // DateTime.dat_Stamp is now filled
DateTime.dat_Format = FORMAT_DEF;
DateTime.dat_Flags = NULL;
DateTime.dat_StrDate = datestring;
DateTime.dat_StrDay = weekdaystring;
DateTime.dat_StrTime = NULL;
if (DateToStr(&DateTime))
{ strcpy(about[1].text, weekdaystring);
strcat(about[1].text, " ");
strcat(about[1].text, datestring);
} }
strcpy(about[2].text, COPYRIGHT);
strcpy(about[3].text, GetCatalogStr(li.li_Catalog, MSG_BY, "By"));
strcat(about[3].text, " James R. Jacobs");
monstertypes[0] = GetCatalogStr(li.li_Catalog, MSG_DRAGON, "Dragon");
monstertypes[1] = GetCatalogStr(li.li_Catalog, MSG_DROW , "Drow" );
monstertypes[2] = GetCatalogStr(li.li_Catalog, MSG_GIANT , "Giant" );
monstertypes[3] = GetCatalogStr(li.li_Catalog, MSG_GHOST , "Ghost" );
monstertypes[4] = GetCatalogStr(li.li_Catalog, MSG_TROLL , "Troll" );
monstertypes[5] = GetCatalogStr(li.li_Catalog, MSG_WITCH , "Witch" );
monstertypes[6] = GetCatalogStr(li.li_Catalog, MSG_HYDRA , "Hydra" );
monstertypes[7] = GetCatalogStr(li.li_Catalog, MSG_SEA_SERPENT, "Sea Serpent");
rune[0].desc = GetCatalogStr(li.li_Catalog, MSG_THE_GODS, "rune of the gods");
rune[1].desc = GetCatalogStr(li.li_Catalog, MSG_TIME , "rune of time" );
rune[2].desc = GetCatalogStr(li.li_Catalog, MSG_PROPERTY, "rune of property");
rune[3].desc = GetCatalogStr(li.li_Catalog, MSG_HEALING , "rune of healing" );
rune[4].desc = GetCatalogStr(li.li_Catalog, MSG_FURY , "rune of fury" );
rune[5].desc = GetCatalogStr(li.li_Catalog, MSG_THE_SUN , "rune of the sun" );
for (whichcountry = 36; whichcountry <= 39; whichcountry++)
{ world[whichcountry].name = GetCatalogStr(li.li_Catalog, MSG_ATLANTIC_OCEAN , "Atlantic Ocean" );
}
for (whichcountry = 40; whichcountry <= 42; whichcountry++)
{ world[whichcountry].name = GetCatalogStr(li.li_Catalog, MSG_IRISH_SEA , "Irish Sea" );
}
for (whichcountry = 43; whichcountry <= 44; whichcountry++)
{ world[whichcountry].name = GetCatalogStr(li.li_Catalog, MSG_ENGLISH_CHANNEL, "English Channel");
}
for (whichcountry = 45; whichcountry <= 62; whichcountry++)
{ if (whichcountry < 47 || whichcountry > 48)
{ world[whichcountry].name = GetCatalogStr(li.li_Catalog, MSG_NORTH_SEA , "North Sea" );
} }
for (whichcountry = 63; whichcountry <= 65; whichcountry++)
{ world[whichcountry].name = GetCatalogStr(li.li_Catalog, MSG_BALTIC_SEA, "Baltic Sea");
}
treasure[BROSUNGNECKLACE].name = GetCatalogStr(li.li_Catalog, MSG_BROSUNG_NECKLACE , "Brosung Necklace");
treasure[MAGICSHIRT].name = GetCatalogStr(li.li_Catalog, MSG_MAGIC_SHIRT , "Magic Shirt" );
treasure[MAILCOAT].name = GetCatalogStr(li.li_Catalog, MSG_MAIL_COAT , "Mail Coat" );
treasure[HEALINGPOTION].name = GetCatalogStr(li.li_Catalog, MSG_HEALING_POTION , "Healing Potion" );
treasure[TELEPORTSCROLL].name = GetCatalogStr(li.li_Catalog, MSG_TELEPORT_SCROLL , "Teleport Scroll" );
NewMenu[INDEX_PROJECT].nm_Label = GetCatalogStr(li.li_Catalog, MSG_PROJECT , "Project" );
NewMenu[INDEX_NEW].nm_Label = GetCatalogStr(li.li_Catalog, MSG_NEW , "New" );
NewMenu[INDEX_NEW].nm_CommKey = GetCatalogStr(li.li_Catalog, MSG_SHORTCUT_NEW , "N" );
NewMenu[INDEX_OPEN].nm_Label = GetCatalogStr(li.li_Catalog, MSG_OPEN , "Open..." );
NewMenu[INDEX_OPEN].nm_CommKey = GetCatalogStr(li.li_Catalog, MSG_SHORTCUT_OPEN , "O" );
NewMenu[INDEX_SAVE].nm_Label = GetCatalogStr(li.li_Catalog, MSG_SAVE , "Save" );
NewMenu[INDEX_SAVE].nm_CommKey = GetCatalogStr(li.li_Catalog, MSG_SHORTCUT_SAVE , "S" );
NewMenu[INDEX_SAVE_AS].nm_Label = GetCatalogStr(li.li_Catalog, MSG_SAVE_AS , "Save As..." );
NewMenu[INDEX_SAVE_AS].nm_CommKey = GetCatalogStr(li.li_Catalog, MSG_SHORTCUT_SAVE_AS , "A" );
NewMenu[INDEX_QUIT].nm_Label = GetCatalogStr(li.li_Catalog, MSG_QUIT , "Quit" );
NewMenu[INDEX_QUIT].nm_CommKey = GetCatalogStr(li.li_Catalog, MSG_SHORTCUT_QUIT , "Q" );
NewMenu[INDEX_SETTINGS].nm_Label = GetCatalogStr(li.li_Catalog, MSG_SETTINGS , "Settings" );
NewMenu[INDEX_SHOW_TITLEBAR].nm_Label = GetCatalogStr(li.li_Catalog, MSG_SHOW_TITLEBAR , "Show Titlebar?" );
NewMenu[INDEX_SHOW_TITLEBAR].nm_CommKey = GetCatalogStr(li.li_Catalog, MSG_SHORTCUT_S_T_B , "B" );
NewMenu[INDEX_HELP].nm_Label = GetCatalogStr(li.li_Catalog, MSG_HELP , "Help" );
NewMenu[INDEX_GAME_SUMMARY].nm_Label = GetCatalogStr(li.li_Catalog, MSG_GAME_SUMMARY2 , "Game Summary..." );
NewMenu[INDEX_GAME_SUMMARY].nm_CommKey = GetCatalogStr(li.li_Catalog, MSG_SHORTCUT_GAME_SUMMARY, "G" );
NewMenu[INDEX_HELP_1].nm_Label = GetCatalogStr(li.li_Catalog, MSG_HELP_1 , "Runes..." );
NewMenu[INDEX_HELP_2].nm_Label = GetCatalogStr(li.li_Catalog, MSG_HELP_2 , "Spells..." );
NewMenu[INDEX_HELP_3].nm_Label = GetCatalogStr(li.li_Catalog, MSG_HELP_3 , "Swords..." );
NewMenu[INDEX_HELP_4].nm_Label = GetCatalogStr(li.li_Catalog, MSG_HELP_4 , "Treasures..." );
NewMenu[INDEX_ABOUT].nm_Label = GetCatalogStr(li.li_Catalog, MSG_ABOUT2 , "About..." );
// we run in English if there is a locale problem
resettime();
if (!(GfxBase = (struct GfxBase *) OpenLibrary("graphics.library", 39L)))
{ DisplayAlert(AT_Recovery, "\0\20\20Saga: Can't open graphics.library V39+!\0", 24);
cleanexit(EXIT_FAILURE);
}
if (!(GadToolsBase = (struct GadToolsBase *) OpenLibrary("gadtools.library", 0L)))
{ DisplayAlert(AT_Recovery, "\0\20\20Saga: Can't open gadtools.library!\0", 24);
cleanexit(EXIT_FAILURE);
}
if (!(ASLBase = (struct ASLBase *) OpenLibrary("asl.library", 38L)))
{ DisplayAlert(AT_Recovery, "\0\20\20Saga: Can't open ASL.library V38+!\0", 24);
cleanexit(EXIT_FAILURE);
}
if
( (DiskFontBase = (struct DiskFontBase *) OpenLibrary("diskfont.library", 0L))
&& (FontPtr = (struct TextFont *) OpenDiskFont(&WormWars8))
)
{ fonttag = (ULONG) &WormWars8;
} else
{ fonttag = (ULONG) &Topaz8;
}
hero[BEOWULF ].control = HUMAN;
hero[BRUNHILD ].control = NONE;
hero[EGIL ].control = NONE;
hero[RAGNAR ].control = AMIGA;
hero[SIEGFRIED].control = NONE;
hero[STARKAD ].control = NONE;
ok = FALSE;
if (FileHandle = Open("PROGDIR:Saga.config", MODE_OLDFILE))
{ if (Read(FileHandle, IOBuffer, CONFIGLENGTH) == CONFIGLENGTH)
{ ok = TRUE;
for (whichhero = 0; whichhero <= HEROES; whichhero++)
{ hero[whichhero].control = (SLONG) ((SBYTE) IOBuffer[whichhero]);
}
DisplayID = (ULONG) ( (IOBuffer[ 6] * 16777216)
+ (IOBuffer[ 7] * 65536)
+ (IOBuffer[ 8] * 256)
+ IOBuffer[ 9] );
DisplayWidth = (ULONG) ( (IOBuffer[10] * 16777216)
+ (IOBuffer[11] * 65536)
+ (IOBuffer[12] * 256)
+ IOBuffer[13] );
DisplayHeight = (ULONG) ( (IOBuffer[14] * 16777216)
+ (IOBuffer[15] * 65536)
+ (IOBuffer[16] * 256)
+ IOBuffer[17] );
DisplayDepth = (UWORD) ( (IOBuffer[18] * 256)
+ IOBuffer[19] );
speed = (WORD) IOBuffer[20];
titlebar = (FLAG) IOBuffer[21];
advanced = (FLAG) IOBuffer[22];
}
Close(FileHandle);
// FileHandle = NULL;
}
if (advanced)
{ monsters = 30;
treasures = 5;
} else
{ monsters = 26;
treasures = 3;
}
/* argument parsing */
if (argc) /* started from CLI */
{ if (!(ArgsPtr = ReadArgs
( "BEOWULF/K,BRUNHILD/K,EGIL/K,RAGNAR/K,SIEGFRIED/K,STARKAD/K,NODBUF/S,FILE",
(LONG *) args,
NULL
)))
{ Printf
( "%s: %s "
"[BEOWULF=HUMAN|AMIGA|NONE] "
"[BRUNHILD=HUMAN|AMIGA|NONE] "
"[EGIL=HUMAN|AMIGA|NONE] "
"[RAGNAR=HUMAN|AMIGA|NONE] "
"[SIEGFRIED=HUMAN|AMIGA|NONE] "
"[STARKAD=HUMAN|AMIGA|NONE] "
"[[FILE=]<savedgame>]\n",
GetCatalogStr(li.li_Catalog, MSG_USAGE, "Usage"),
argv[0]
);
cleanexit(EXIT_FAILURE);
}
for (whichhero = 0; whichhero <= HEROES; whichhero++)
{ if (args[whichhero])
{ if (!stricmp((STRPTR) args[whichhero], "HUMAN"))
{ hero[whichhero].control = HUMAN;
} elif (!stricmp((STRPTR) args[whichhero], "AMIGA"))
{ hero[whichhero].control = AMIGA;
} elif (!stricmp((STRPTR) args[whichhero], "NONE"))
{ hero[whichhero].control = NONE;
} else
{ Printf("%s: Hero control must be HUMAN, AMIGA or NONE\n", argv[0]); // localize?
} } }
if (args[6])
{ nodbuf = TRUE;
}
if (args[7])
{ strcpy(pathname, (STRPTR) args[7]);
cliload = TRUE;
} }
strcpy(smrstring, "Saga: ");
strcat(smrstring, GetCatalogStr(li.li_Catalog, MSG_S_M_R, "Screen Mode Requester"));
if (!ok)
{ if (!(smr = (struct ScreenModeRequester *) AllocAslRequestTags
( ASL_ScreenModeRequest,
ASLSM_TitleText, smrstring,
ASLSM_InitialDisplayID, HIRES_KEY | PAL_MONITOR_ID | LACE,
ASLSM_InitialDisplayWidth, SCREENXPIXEL,
ASLSM_InitialDisplayHeight, SCREENYPIXEL,
ASLSM_InitialDisplayDepth, DEPTH,
ASLSM_DoWidth, TRUE,
ASLSM_DoHeight, TRUE,
ASLSM_DoDepth, TRUE,
ASLSM_MinWidth, SCREENXPIXEL,
ASLSM_MinHeight, SCREENYPIXEL,
ASLSM_MinDepth, MINDEPTH,
TAG_DONE
)))
{ DisplayAlert(AT_Recovery, "\0\20\20Saga: Can't create ASL screen mode request!\0", 24);
cleanexit(EXIT_FAILURE);
}
if (AslRequest(smr, 0L))
{ DisplayID = smr->sm_DisplayID;
DisplayWidth = smr->sm_DisplayWidth;
DisplayHeight = smr->sm_DisplayHeight;
DisplayDepth = smr->sm_DisplayDepth;
FreeAslRequest(smr);
} else
{ FreeAslRequest(smr);
cleanexit(EXIT_SUCCESS);
} }
if
( GetDisplayInfoData(NULL, (UBYTE *) &QueryInfo, sizeof(struct DisplayInfo), DTAG_DISP, DisplayID)
&& (QueryInfo.PropertyFlags & DIPF_IS_PAL)
)
{ aga = TRUE;
if (!nodbuf)
{ dbuf = TRUE;
// Printf("Saga: Double buffering activated.\n");
} }
if (LockPubScreen("SAGA"))
{ publictag = TAG_IGNORE;
} else
{ publictag = SA_PubName;
}
ScreenPtr = (struct Screen *) OpenScreenTags
( NULL,
SA_Width, DisplayWidth,
SA_Height, DisplayHeight,
SA_Depth, DisplayDepth,
SA_DisplayID, DisplayID,
SA_Behind, TRUE,
SA_AutoScroll, TRUE,
SA_ShowTitle, titlebar,
SA_Title, TITLEBAR,
SA_Font, fonttag,
publictag, "SAGA",
SA_Colors32, table1,
SA_Pens, Pens,
TAG_DONE
); // we can't use interleaving on AGA screens if we want double buffering
if (!ScreenPtr)
{ DisplayAlert(AT_Recovery, "\0\20\20Saga: Can't open screen!\0", 24);
cleanexit(EXIT_FAILURE);
}
saveconfig = TRUE;
if (publictag == SA_PubName)
{ PubScreenStatus(ScreenPtr, NULL); // take the screen public
}
for (whichcountry = 36; whichcountry <= 65; whichcountry++)
{ SetRGB32(&ScreenPtr->ViewPort, 8 + whichcountry, 0x00000000, 0x00000000, 0x99999999);
}
LoadRGB32(&(ScreenPtr->ViewPort), table2);
// this must be done before the menus are set up
if (titlebar)
{ NewMenu[INDEX_SHOW_TITLEBAR].nm_Flags |= CHECKED;
}
/* GadTools */
if (!(VisualInfoPtr = (APTR) GetVisualInfo(ScreenPtr, TAG_DONE)))
{ DisplayAlert(AT_Recovery, "\0\20\20Saga: Can't get GadTools visual info!\0", 24);
cleanexit(EXIT_FAILURE);
}
for (whichhero = 0; whichhero <= HEROES; whichhero++)
{ CycleGadget[whichhero].ng_VisualInfo = VisualInfoPtr;
}
SpeedGadget.ng_VisualInfo =
AdvancedGadget.ng_VisualInfo = VisualInfoPtr;
if (!(MenuPtr = (struct Menu *) CreateMenus(NewMenu, TAG_DONE)))
{ DisplayAlert(AT_Recovery, "\0\20\20Saga: Can't create menus!\0", 24);
cleanexit(EXIT_FAILURE);
}
if (!(LayoutMenus(MenuPtr, VisualInfoPtr, GTMN_NewLookMenus, TRUE, TAG_DONE)))
{ DisplayAlert(AT_Recovery, "\0\20\20Saga: Can't lay out menus!\0", 24);
cleanexit(EXIT_FAILURE);
}
if (!(PrevGadgetPtr = (struct Gadget *) CreateContext(&GListPtr)))
{ DisplayAlert(AT_Recovery, "\0\20\20Saga: Can't create GadTools context!\0", 24);
cleanexit(EXIT_FAILURE);
}
for (whichhero = 0; whichhero <= HEROES; whichhero++)
{ CycleGadgetPtr[whichhero] = PrevGadgetPtr = (struct Gadget *) CreateGadget
( CYCLE_KIND,
PrevGadgetPtr,
&CycleGadget[whichhero],
GTCY_Labels, CycleOptions,
GTCY_Active, hero[whichhero].control,
TAG_DONE
);
}
SpeedGadgetPtr = PrevGadgetPtr = (struct Gadget *) CreateGadget
( SLIDER_KIND,
PrevGadgetPtr,
&SpeedGadget,
GA_RelVerify, TRUE,
GTSL_Min, 0,
GTSL_Max, 6,
GTSL_Level, speed,
GT_Underscore, '_',
TAG_DONE
);
AdvancedGadgetPtr = PrevGadgetPtr = (struct Gadget *) CreateGadget
( CHECKBOX_KIND,
PrevGadgetPtr,
&AdvancedGadget,
GA_RelVerify, TRUE,
GTCB_Checked, (BOOL) advanced,
GT_Underscore, '_',
TAG_DONE
);
if (dbuf)
{ if (!(ScreenBuf[0] = AllocScreenBuffer(ScreenPtr, NULL, SB_SCREEN_BITMAP)))
{ DisplayAlert(AT_Recovery, "\0\20\20Saga: Can't allocate original screen buffer!\0", 24);
cleanexit(EXIT_FAILURE);
} }
/* main window */
if (!(MainWindowPtr = (struct Window *) OpenWindowTags(NULL,
WA_Left, 0,
WA_Top, 0,
WA_Width, DisplayWidth,
WA_Height, DisplayHeight,
WA_Backdrop, TRUE,
WA_IDCMP, IDCMP_RAWKEY
| IDCMP_VANILLAKEY
| IDCMP_MOUSEBUTTONS
| IDCMP_INTUITICKS
| IDCMP_CLOSEWINDOW
| IDCMP_REFRESHWINDOW
| IDCMP_MENUPICK
| IDCMP_MENUVERIFY
| CYCLEIDCMP
| BUTTONIDCMP,
WA_Flags, WFLG_BORDERLESS,
WA_Gadgets, GListPtr,
WA_CustomScreen, ScreenPtr,
WA_Activate, TRUE,
WA_NewLookMenus, TRUE,
TAG_DONE)))
{ DisplayAlert(AT_Recovery, "\0\20\20Saga: Can't open window!\0", 24);
cleanexit(EXIT_FAILURE);
}
/* We could use SCREENXPIXEL and SCREENYPIXEL instead, except that titlebar hiding
would not then work correctly. */
/* redirection of AmigaDOS system requesters */
OldWindowPtr = ProcessPtr->pr_WindowPtr;
ProcessPtr->pr_WindowPtr = (APTR) MainWindowPtr;
if (!(ASLRqPtr = AllocAslRequestTags(ASL_FileRequest, ASL_Pattern, "#?.saga", ASL_Window, MainWindowPtr, TAG_DONE)))
{ DisplayAlert(AT_Recovery, "\0\20\20Saga: Can't create ASL file request!\0", 24);
cleanexit(EXIT_FAILURE);
}
SetMenuStrip(MainWindowPtr, MenuPtr);
// clean to here
createcounters();
// dirty by here
ScreenToFront(ScreenPtr);
while (1)
{ titlescreen();
if (!loaded)
{ newgame();
}
gameloop();
} }
MODULE void gameloop(void)
{ SLONG bestglory = 0,
besthero = -1, // to avoid spurious compiler warnings
countertype,
fastest,
heroes = 0,
strongest,
strongestjarl,
result,
whichhero,
whichjarl,
whichcountry,
whichmonster,
whichtreasure,
whichsord,
winners = 0;
FLAG done,
transfer;
UWORD code,
qual;
WORD mousey;
ULONG class;
struct IntuiMessage* MsgPtr;
struct MenuItem* ItemPtr;
do
{ strcpy(titlestring, TITLEBAR);
strcat(titlestring, ": ");
sprintf
( saystring,
"%s %ld %s %ld",
GetCatalogStr(li.li_Catalog, MSG_TURN, "Turn"),
turn,
GetCatalogStr(li.li_Catalog, MSG_OF, "of"),
TURNS
);
strcat(titlestring, saystring);
strcat(saystring, "...");
SetWindowTitles(MainWindowPtr, (UBYTE *) -1, titlestring); // this is not copied, it is a pointer
say(LOWER);
hint
( (STRPTR) GetCatalogStr(li.li_Catalog, MSG_OK, "OK"),
(STRPTR) GetCatalogStr(li.li_Catalog, MSG_OK, "OK")
);
OnMenu(MainWindowPtr, FULLMENUNUM(MN_PROJECT, IN_NEW, NOSUB));
OnMenu(MainWindowPtr, FULLMENUNUM(MN_PROJECT, IN_SAVE, NOSUB));
OnMenu(MainWindowPtr, FULLMENUNUM(MN_PROJECT, IN_SAVEAS, NOSUB));
result = getevent(MULTIKEYBOARD, NULL);
if (result == -4)
{ for (whichhero = 0; whichhero <= HEROES; whichhero++)
{ hero[whichhero].alive = FALSE;
hero[whichhero].verydead = TRUE;
}
gameover = TRUE;
}
OffMenu(MainWindowPtr, FULLMENUNUM(MN_PROJECT, IN_NEW, NOSUB));
OffMenu(MainWindowPtr, FULLMENUNUM(MN_PROJECT, IN_SAVE, NOSUB));
OffMenu(MainWindowPtr, FULLMENUNUM(MN_PROJECT, IN_SAVEAS, NOSUB));
if (!gameover)
{ for (whichhero = 0; whichhero <= HEROES; whichhero++)
{ if (!hero[whichhero].alive && !hero[whichhero].verydead)
{ transfer = FALSE;
for (whichjarl = 0; whichjarl <= JARLS; whichjarl++)
{ if (jarl[whichjarl].alive && jarl[whichjarl].hero == whichhero)
{ transfer = TRUE;
break; // for speed
} }
if (hero[whichhero].control == AMIGA)
{ if (transfer)
{ strongest = fastest = strongestjarl = 0;
for (whichjarl = 0; whichjarl <= JARLS; whichjarl++)
{ if
( jarl[whichjarl].alive
&& jarl[whichjarl].hero == whichhero
)
{ if (jarl[whichjarl].strength > strongest)
{ strongest = jarl[whichjarl].strength;
fastest = jarl[whichjarl].moves;
strongestjarl = whichjarl;
} elif (jarl[whichjarl].strength == strongest)
{ if (jarl[whichjarl].moves > fastest)
{ strongest = jarl[whichjarl].strength;
fastest = jarl[whichjarl].moves;
strongestjarl = whichjarl;
} } } }
sprintf
( saystring,
"%s %s %s %s (%ld-%ld).",
GetCatalogStr(li.li_Catalog, MSG_DEAD_HERO, "Dead hero"),
hero[whichhero].name,
GetCatalogStr(li.li_Catalog, MSG_PROMOTES_JARL, "promotes jarl"),
jarl[strongestjarl].name,
jarl[strongestjarl].strength,
jarl[strongestjarl].moves
);
promote(whichhero, strongestjarl); // order-dependent
} else
{ if (turn > TURNS / 2)
{ withdraw(whichhero);
sprintf
( saystring,
"%s %s %s.",
GetCatalogStr(li.li_Catalog, MSG_DEAD_HERO, "Dead hero"),
hero[whichhero].name,
GetCatalogStr(li.li_Catalog, MSG_WITHDRAWS_FROM_PLAY, "withdraws from play")
);
} else
{ newhero(whichhero, FALSE);
sprintf
( saystring,
"%s %s %s.",
GetCatalogStr(li.li_Catalog, MSG_DEAD_HERO, "Dead hero"),
hero[whichhero].name,
GetCatalogStr(li.li_Catalog, MSG_RESTARTS, "restarts")
);
} }
say(LOWER);
anykey();
} elif (hero[whichhero].control == HUMAN)
{ sprintf
( saystring,
"%s %s, (%s)%s/(%s)%s",
GetCatalogStr(li.li_Catalog, MSG_DEAD_HERO, "Dead hero"),
hero[whichhero].name,
GetCatalogStr(li.li_Catalog, MSG_CHAR_WITHDRAW, "W"),
GetCatalogStr(li.li_Catalog, MSG_UNCHAR_WITHDRAW, "ithdraw"),
GetCatalogStr(li.li_Catalog, MSG_CHAR_RESTART, "R"),
GetCatalogStr(li.li_Catalog, MSG_UNCHAR_RESTART, "estart")
);
if (transfer)
{ sprintf
( saystring2,
"/(%s)%s?",
GetCatalogStr(li.li_Catalog, MSG_CHAR_TRANSFER, "T"),
GetCatalogStr(li.li_Catalog, MSG_UNCHAR_TRANSFER, "ransfer")
);
strcat(saystring, saystring2);
} else
{ strcat(saystring, "?");
}
say(LOWER);
do
{ result = getevent(WRKEYBOARD, NULL);
} while
( result != onekey[ONEKEY_WITHDRAW]
&& result != onekey[ONEKEY_RESTART]
&& (!transfer || result != onekey[ONEKEY_TRANSFER])
);
if (result == onekey[ONEKEY_TRANSFER])
{ sprintf
( saystring,
"%s %s, %s?",
GetCatalogStr(li.li_Catalog, MSG_DEAD_HERO, "Dead hero"),
hero[whichhero].name,
GetCatalogStr(li.li_Catalog, MSG_S_W_J_T_P, "select which jarl to promote")
);
say(LOWER);
do
{ whichjarl = getevent(COUNTER, &countertype);
} while
( whichjarl < 0
|| countertype != JARL
|| jarl[whichjarl].hero != whichhero
);
promote(whichhero, whichjarl);
} elif (result == onekey[ONEKEY_WITHDRAW])
{ withdraw(whichhero);
} elif (result == onekey[ONEKEY_RESTART])
{ newhero(whichhero, FALSE);
} } } }
phase1(); // movement
phase2(); // combat
phase3(); // kingdoms
/* "4. PLACE MONSTERS. A number of monsters equal to the number
of heroes in play are randomly placed face up by rolling two dice
and placing the monster in the area indicated. (This is done every
turn until all counters are used. "Dead" monsters may not be
reused."
It's arguable whether monsters and jarls should be added
at the end of the last turn. A strict reading of the rules
would indicate that they should, but in practical terms it
is better not to - adding them causes the new counters to
appear on screen just before the screen is blanked, which
is an annoying effect. */
if (turn < TURNS)
{ place_monsters(); // phase 4
/* "5. PLACE jarls. A number of jarls equal to the number of
heroes in play are randomly placed face up by rolling two dice
and placing the jarl in the area indicated. (This is done every
turn until all counters are used. "Dead" jarls may not be
reused." */
place_jarls(); // phase 5
refreshcounters();
}
/* 6. MARK TURN. One turn is marked off. */
turn++;
}
} while (turn <= TURNS && !gameover);
/* "At the end of the 20th turn the game is over and players total
their glory to determine who has won. The turn should be marked off on
each player's record sheet." */
screenoff();
for (whichhero = 0; whichhero <= HEROES; whichhero++)
{ remove_hero(whichhero, FALSE);
}
for (whichjarl = 0; whichjarl <= JARL; whichjarl++)
{ remove_jarl(whichjarl, FALSE);
}
for (whichmonster = 0; whichmonster <= MONSTERS; whichmonster++)
{ remove_monster(whichmonster, FALSE);
}
for (whichtreasure = 0; whichtreasure <= TREASURES; whichtreasure++)
{ remove_treasure(whichtreasure, FALSE);
}
for (whichsord = 0; whichsord <= SORDS; whichsord++)
{ remove_sord(whichsord, FALSE);
}
// no reason to call refreshcounters() as we are about to blank the screen
for (whichcountry = 0; whichcountry <= 65; whichcountry++)
{ world[whichcountry].hero = -1;
}
clearscreen();
screenon();
if (!gameover)
{ SetDrMd(MainWindowPtr->RPort, JAM1);
SetAPen(MainWindowPtr->RPort, LIGHTGREY);
RectFill(MainWindowPtr->RPort, 320 - 70, 187 + TBSIZE, 320 + 70, 187 + TBSIZE + 11);
if (DisplayDepth >= DEPTH)
{ SetAPen(MainWindowPtr->RPort, WHITE);
Move(MainWindowPtr->RPort, 320 - 70, 187 + TBSIZE - 2);
Draw(MainWindowPtr->RPort, 320 + 70, 187 + TBSIZE - 2);
}
SetAPen(MainWindowPtr->RPort, BLACK);
Move(MainWindowPtr->RPort, 320 - 70, 187 + TBSIZE - 1);
Draw(MainWindowPtr->RPort, 320 + 70, 187 + TBSIZE - 1);
Move(MainWindowPtr->RPort, 320 - 70, 187 + TBSIZE + 12);
Draw(MainWindowPtr->RPort, 320 + 70, 187 + TBSIZE + 12);
strcpy(saystring, GetCatalogStr(li.li_Catalog, MSG_HERO_NAME, "Hero Name"));
Move(MainWindowPtr->RPort, 320 - 70 + 4, 187 + TBSIZE + 8);
Text(MainWindowPtr->RPort, saystring, strlen(saystring));
strcpy(saystring, GetCatalogStr(li.li_Catalog, MSG_GLORY, "Glory"));
Move(MainWindowPtr->RPort, 320 + 70 - (8 * 4) - 4 + (8 * (4 - strlen(saystring))), 187 + TBSIZE + 8);
Text(MainWindowPtr->RPort, saystring, strlen(saystring));
for (whichhero = 0; whichhero <= HEROES; whichhero++)
{ if (hero[whichhero].control != NONE)
{ heroes++;
hero[whichhero].glory += hero[whichhero].wealth / 10;
hero[whichhero].glory += hero[whichhero].luck / 3;
if
( treasure[BROSUNGNECKLACE].possessortype == HERO
&& treasure[BROSUNGNECKLACE].possessor == whichhero
)
{ hero[whichhero].wealth += 20;
}
for (whichjarl = 0; whichjarl <= JARLS; whichjarl++)
{ if (jarl[whichjarl].alive && jarl[whichjarl].hero == whichhero)
{ hero[whichhero].glory += jarl[whichjarl].strength / 2;
if
( treasure[BROSUNGNECKLACE].possessortype == JARL
&& treasure[BROSUNGNECKLACE].possessor == whichjarl
)
{ hero[whichhero].wealth += 20;
} } }
if (hero[whichhero].glory >= 15)
{ SetAPen(MainWindowPtr->RPort, GREEN);
} else
{ SetAPen(MainWindowPtr->RPort, RED);
}
RectFill(MainWindowPtr->RPort, 320 - 70, 187 + TBSIZE + (heroes * SCOREDISTANCE), 320 + 70, 187 + TBSIZE + 11 + (heroes * SCOREDISTANCE));
SetAPen(MainWindowPtr->RPort, BLACK);
Move(MainWindowPtr->RPort, 320 - 70 + 4, 187 + TBSIZE + 8 + (heroes * SCOREDISTANCE));
Text(MainWindowPtr->RPort, hero[whichhero].name, strlen(hero[whichhero].name));
stcl_d(numberstring, hero[whichhero].glory);
Move(MainWindowPtr->RPort, 320 + 70 - (8 * 4) - 4 + (8 * (4 - strlen(numberstring))), 187 + TBSIZE + 8 + (heroes * SCOREDISTANCE));
Text(MainWindowPtr->RPort, numberstring, strlen(numberstring));
Move(MainWindowPtr->RPort, 320 - 70, 199 + TBSIZE + (heroes * SCOREDISTANCE));
Draw(MainWindowPtr->RPort, 320 + 70, 199 + TBSIZE + (heroes * SCOREDISTANCE));
} }
if (DisplayDepth >= DEPTH)
{ SetAPen(MainWindowPtr->RPort, WHITE);
Move(MainWindowPtr->RPort, 249, 185 + TBSIZE);
Draw(MainWindowPtr->RPort, 249, 187 + TBSIZE + ((heroes + 1) * SCOREDISTANCE));
}
SetAPen(MainWindowPtr->RPort, BLACK);
Move(MainWindowPtr->RPort, 250, 187 + TBSIZE);
Draw(MainWindowPtr->RPort, 250, 187 + TBSIZE + ((heroes + 1) * SCOREDISTANCE));
Move(MainWindowPtr->RPort, 340, 187 + TBSIZE);
Draw(MainWindowPtr->RPort, 340, 187 + TBSIZE + ((heroes + 1) * SCOREDISTANCE));
Move(MainWindowPtr->RPort, 390, 187 + TBSIZE);
Draw(MainWindowPtr->RPort, 390, 187 + TBSIZE + ((heroes + 1) * SCOREDISTANCE));
Move(MainWindowPtr->RPort, 391, 187 + TBSIZE);
Draw(MainWindowPtr->RPort, 391, 187 + TBSIZE + ((heroes + 1) * SCOREDISTANCE));
Draw(MainWindowPtr->RPort, 250, 187 + TBSIZE + ((heroes + 1) * SCOREDISTANCE));
strcpy(saystring, GetCatalogStr(li.li_Catalog, MSG_GAME_OVER, "Game over"));
strcat(saystring, "!");
if (heroes > 1)
{ // determine winner
for (whichhero = 0; whichhero <= HEROES; whichhero++)
{ if (hero[whichhero].control != NONE && hero[whichhero].glory >= bestglory)
{ bestglory = hero[whichhero].glory;
} }
for (whichhero = 0; whichhero <= HEROES; whichhero++)
{ if (hero[whichhero].control != NONE && hero[whichhero].glory == bestglory)
{ winners++;
besthero = whichhero;
} }
if (winners == 1)
{ strcat(saystring, " ");
strcat(saystring, hero[besthero].name);
strcat(saystring, " ");
strcat(saystring, GetCatalogStr(li.li_Catalog, MSG_WINS, "wins"));
strcat(saystring, "!");
} }
SetAPen(MainWindowPtr->RPort, BLACK);
Move(MainWindowPtr->RPort, 4 + 1, MESSAGEY + 16 + 1);
Text(MainWindowPtr->RPort, saystring, strlen(saystring));
SetAPen(MainWindowPtr->RPort, WHITE);
Move(MainWindowPtr->RPort, 4 , MESSAGEY + 16 );
Text(MainWindowPtr->RPort, saystring, strlen(saystring));
/* say(LOWER);
hint
( (STRPTR) GetCatalogStr(li.li_Catalog, MSG_OK, "OK"),
(STRPTR) GetCatalogStr(li.li_Catalog, MSG_OK, "OK")
); */
Delay(50);
clearkybd();
done = FALSE;
do
{ Wait(1L << MainWindowPtr->UserPort->mp_SigBit);
MsgPtr = (struct IntuiMessage *) GT_GetIMsg(MainWindowPtr->UserPort);
class = MsgPtr->Class;
code = MsgPtr->Code;
qual = MsgPtr->Qualifier;
mousey = MsgPtr->MouseY;
if (class == IDCMP_MENUVERIFY && code == MENUHOT && mousey > TBSIZE)
{ if (!(qual & IEQUALIFIER_RCOMMAND))
{ MsgPtr->Code = MENUCANCEL;
} }
GT_ReplyIMsg(MsgPtr);
switch(class)
{
case IDCMP_CLOSEWINDOW:
cleanexit(EXIT_SUCCESS);
acase IDCMP_REFRESHWINDOW:
GT_BeginRefresh(MainWindowPtr);
GT_EndRefresh(MainWindowPtr, TRUE);
acase IDCMP_MOUSEBUTTONS:
case IDCMP_VANILLAKEY:
case IDCMP_RAWKEY:
done = TRUE;
acase IDCMP_MENUPICK:
while (code != MENUNULL)
{ ItemPtr = ItemAddress(MenuPtr, code);
switch (MENUNUM(code))
{
case MN_PROJECT:
switch (ITEMNUM(code))
{
case IN_QUIT:
cleanexit(EXIT_SUCCESS);
adefault:
// IN_OPEN
break;
}
acase MN_SETTINGS:
switch(ITEMNUM(code))
{
case IN_SHOW_TITLEBAR:
if (ItemPtr->Flags & CHECKED)
{ titlebar = TRUE;
} else
{ titlebar = FALSE;
}
ShowTitle(ScreenPtr, titlebar);
adefault:
break;
}
acase MN_HELP:
switch(ITEMNUM(code))
{
case IN_GAME_SUMMARY:
summarywindow();
acase IN_HELP_1:
docwindow(1);
acase IN_HELP_2:
docwindow(2);
acase IN_HELP_3:
docwindow(3);
acase IN_HELP_4:
docwindow(4);
acase IN_ABOUT:
helpabout();
adefault:
break;
}
adefault:
break;
}
code = ItemPtr->NextSelect;
}
adefault: // IDCMP_MENUVERIFY, etc.
break;
}
} while (!done);
} }
EXPORT void cleanexit(SLONG rc)
{ BPTR FileHandle /* = NULL */ ;
SLONG whichhero;
destroycounters();
if (ASLRqPtr)
{ FreeAslRequest(ASLRqPtr);
ASLRqPtr = NULL;
}
if (OldWindowPtr)
{ ProcessPtr->pr_WindowPtr = OldWindowPtr;
}
/* It does not matter whether there are outstanding messages for a
window when it is closed, provided that the window does not use a
shared IDCMP message port. */
if (InfoWindowPtr)
{ CloseWindow(InfoWindowPtr);
InfoWindowPtr = NULL;
}
if (HelpWindowPtr)
{ CloseWindow(HelpWindowPtr);
HelpWindowPtr = NULL;
}
if (MainWindowPtr)
{ ClearMenuStrip(MainWindowPtr);
CloseWindow(MainWindowPtr);
MainWindowPtr = NULL;
}
if (GListPtr)
{ FreeGadgets(GListPtr);
GListPtr = NULL;
}
if (MenuPtr)
{ FreeMenus(MenuPtr);
MenuPtr = NULL;
}
if (VisualInfoPtr)
{ FreeVisualInfo(VisualInfoPtr);
VisualInfoPtr = NULL;
}
if (ScreenPtr)
{ if (ScreenBuf[1])
{ FreeScreenBuffer(ScreenPtr, ScreenBuf[1]);
ScreenBuf[1] = NULL;
}
if (ScreenBuf[0])
{ FreeScreenBuffer(ScreenPtr, ScreenBuf[0]);
ScreenBuf[0] = NULL;
}
CloseScreen(ScreenPtr);
ScreenPtr = NULL;
}
if (FontPtr)
{ CloseFont(FontPtr);
FontPtr = NULL;
}
if (DiskFontBase)
{ CloseLibrary((struct Library *) DiskFontBase);
DiskFontBase = NULL;
}
if (ASLBase)
{ CloseLibrary((struct Library *) ASLBase);
ASLBase = NULL;
}
if (GadToolsBase)
{ CloseLibrary((struct Library *) GadToolsBase);
GadToolsBase = NULL;
}
if (GfxBase)
{ CloseLibrary((struct Library *) GfxBase);
GfxBase = NULL;
}
if (LocaleBase)
{ CloseCatalog(li.li_Catalog);
CloseLibrary((struct Library *) LocaleBase);
LocaleBase = NULL;
}
if (IntuitionBase)
{ OpenWorkBench();
CloseLibrary((struct Library *) IntuitionBase);
IntuitionBase = NULL;
}
if (ArgsPtr)
{ FreeArgs(ArgsPtr);
ArgsPtr = NULL;
}
if (saveconfig)
{ for (whichhero = 0; whichhero <= HEROES; whichhero++)
{ IOBuffer[whichhero] = (SBYTE) hero[whichhero].control;
}
IOBuffer[ 6] = (UBYTE) (DisplayID / 16777216);
IOBuffer[ 7] = (UBYTE) ((DisplayID % 16777216) / 65536);
IOBuffer[ 8] = (UBYTE) (((DisplayID % 16777216) % 65536) / 256);
IOBuffer[ 9] = (UBYTE) (((DisplayID % 16777216) % 65536) % 256);
IOBuffer[10] = (UBYTE) (DisplayWidth / 16777216);
IOBuffer[11] = (UBYTE) ((DisplayWidth % 16777216) / 65536);
IOBuffer[12] = (UBYTE) (((DisplayWidth % 16777216) % 65536) / 256);
IOBuffer[13] = (UBYTE) (((DisplayWidth % 16777216) % 65536) % 256);
IOBuffer[14] = (UBYTE) (DisplayHeight / 16777216);
IOBuffer[15] = (UBYTE) ((DisplayHeight % 16777216) / 65536);
IOBuffer[16] = (UBYTE) (((DisplayHeight % 16777216) % 65536) / 256);
IOBuffer[17] = (UBYTE) (((DisplayHeight % 16777216) % 65536) % 256);
IOBuffer[18] = (UBYTE) (DisplayDepth / 65536);
IOBuffer[19] = (UBYTE) (DisplayDepth % 65536);
IOBuffer[20] = (UBYTE) speed;
IOBuffer[21] = (UBYTE) titlebar;
IOBuffer[22] = (UBYTE) advanced;
if (FileHandle = Open("PROGDIR:Saga.config", MODE_NEWFILE))
{ Write(FileHandle, IOBuffer, CONFIGLENGTH);
Close(FileHandle);
// FileHandle = NULL;
} }
exit(rc); // End of program.
}
EXPORT void say(SLONG position)
{ AUTO SLONG length;
PERSIST TEXT oldupper[80 + 1] = "";
length = strlen(saystring);
SetAPen(MainWindowPtr->RPort, BLACK);
if (position == UPPER)
{ if (strcmp(saystring, oldupper))
{ RectFill
( MainWindowPtr->RPort,
0, MESSAGEY,
639, MESSAGEY + 7
);
SetAPen(MainWindowPtr->RPort, WHITE);
Move(MainWindowPtr->RPort, 4, MESSAGEY + 6);
Text(MainWindowPtr->RPort, saystring, length);
strcpy(oldupper, saystring);
} }
else
{ assert(position == LOWER);
RectFill
( MainWindowPtr->RPort,
0, MESSAGEY + 10,
639, MESSAGEY + 27
);
SetAPen(MainWindowPtr->RPort, WHITE);
Move(MainWindowPtr->RPort, 4, MESSAGEY + 16);
if (length > 79)
{ Text(MainWindowPtr->RPort, saystring, 79);
Move(MainWindowPtr->RPort, 4, MESSAGEY + 26);
Text(MainWindowPtr->RPort, &saystring[79], length - 79);
} else
{ Text(MainWindowPtr->RPort, saystring, length);
} } }
EXPORT SLONG getevent(SLONG mode, SLONG* countertype)
{ AUTO UWORD code,
qual;
AUTO ULONG class;
AUTO struct IntuiMessage* MsgPtr;
AUTO LONG country;
AUTO SLONG counter,
ticks = 0;
AUTO WORD mousex, mousey;
AUTO struct MenuItem* ItemPtr;
PERSIST SLONG cheat = 0;
/* return codes:
-4: Escape
-3: spacebar
-2: backspace
-1: invalid country */
switch (mode)
{
case ANYKEY:
hint
( (STRPTR) GetCatalogStr(li.li_Catalog, MSG_OK, "OK"),
(STRPTR) GetCatalogStr(li.li_Catalog, MSG_OK, "OK")
);
break;
case YNKEYBOARD:
hint
( (STRPTR) GetCatalogStr(li.li_Catalog, MSG_YES, "Yes"),
(STRPTR) GetCatalogStr(li.li_Catalog, MSG_NO, "No")
);
break;
case GLKEYBOARD:
hint
( (STRPTR) GetCatalogStr(li.li_Catalog, MSG_GLORY, "Glory"),
(STRPTR) GetCatalogStr(li.li_Catalog, MSG_LUCK, "Luck")
);
break;
case WRKEYBOARD:
hint
( (STRPTR) GetCatalogStr(li.li_Catalog, MSG_WITHDRAW, "Withdraw"),
(STRPTR) GetCatalogStr(li.li_Catalog, MSG_RESTART, "Restart")
);
break;
default:
// Routines which use MULTIKEYBOARD or COUNTER or COUNTRY must call hint() themselves
break;
}
clearkybd();
while(1)
{ Wait(1L << MainWindowPtr->UserPort->mp_SigBit);
while (MsgPtr = (struct IntuiMessage *) GT_GetIMsg(MainWindowPtr->UserPort))
{ class = MsgPtr->Class;
code = MsgPtr->Code;
mousex = MsgPtr->MouseX;
mousey = MsgPtr->MouseY;
qual = MsgPtr->Qualifier;
if (class == IDCMP_MENUVERIFY && code == MENUHOT && mousey > TBSIZE)
{ if (!(qual & IEQUALIFIER_RCOMMAND))
{ MsgPtr->Code = MENUCANCEL;
} }
GT_ReplyIMsg(MsgPtr);
switch(class)
{
case IDCMP_CLOSEWINDOW:
cleanexit(EXIT_SUCCESS);
break;
case IDCMP_REFRESHWINDOW:
GT_BeginRefresh(MainWindowPtr);
GT_EndRefresh(MainWindowPtr, TRUE);
break;
case IDCMP_MOUSEBUTTONS:
if
( code == SELECTDOWN
&& !(qual & IEQUALIFIER_REPEAT)
)
{ if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
{ counter = checkcounters(mousex, mousey, countertype);
if (counter == -1)
{ country = checkcountry(mousex, mousey);
if (country >= 0)
{ infowindow(KINGDOM, country);
} else
{ summarywindow();
} }
else
{ infowindow(*(countertype), counter);
} }
else
{ switch(mode)
{
case MULTIKEYBOARD:
case ANYKEY:
return('0');
break;
case YNKEYBOARD:
return(onekey[ONEKEY_YES]);
break;
case GLKEYBOARD:
return(onekey[ONEKEY_GLORY]);
break;
case WRKEYBOARD:
return(onekey[ONEKEY_WITHDRAW]);
break;
case COUNTER:
case COUNTRY:
if (mousey >= MESSAGEY)
{ return(-3);
}
counter = checkcounters(mousex, mousey, countertype);
if (counter == -1)
{ country = checkcountry(mousex, mousey);
*(countertype) = KINGDOM;
flash(country);
return(country);
} else
{ if (mode == COUNTER)
{ return(counter);
}
assert(mode == COUNTRY);
if (*(countertype) == HERO)
{ flash(hero[counter].where);
return(hero[counter].where);
} elif (*(countertype) == JARL)
{ flash(jarl[counter].where);
return(jarl[counter].where);
} elif (*(countertype) == MONSTER)
{ flash(monster[counter].where);
return(monster[counter].where);
} elif (*(countertype) == SORD)
{ flash(sord[counter].where);
return(sord[counter].where);
} elif (*(countertype) == TREASURE)
{ flash(treasure[counter].where);
return(treasure[counter].where);
} }
break;
default:
assert(0);
break;
} } }
elif
( (code == MIDDLEDOWN || code == MENUUP)
&& !(qual & IEQUALIFIER_REPEAT)
)
{ if (mode == MULTIKEYBOARD)
{ return('0');
} elif (mode == YNKEYBOARD)
{ return(onekey[ONEKEY_NO]);
} elif (mode == GLKEYBOARD)
{ return(onekey[ONEKEY_LUCK]);
} elif (mode == WRKEYBOARD)
{ return(onekey[ONEKEY_RESTART]);
} elif (mode != ANYKEY || tickspeed[speed] == -1)
{ return(-3);
} }
break;
case IDCMP_INTUITICKS:
if (mode == ANYKEY && tickspeed[speed] != -1)
{ ticks++;
if (ticks >= tickspeed[speed])
{ return(-3);
} }
counter = checkcounters(mousex, mousey, countertype);
if (counter == -1)
{ country = checkcountry(mousex, mousey);
*(countertype) = KINGDOM;
showcountry(country);
} else
{ if (*(countertype) == HERO)
{ saywho(HERO, counter, FALSE, FALSE);
strcat(saystring, "(");
stcl_d(numberstring, hero[counter].strength);
strcat(saystring, numberstring);
strcat(saystring, "-");
stcl_d(numberstring, hero[counter].moves);
strcat(saystring, numberstring);
strcat(saystring, ")");
say(UPPER);
} elif (*(countertype) == JARL)
{ if (jarl[counter].face == FACEDOWN)
{ strcpy(saystring, GetCatalogStr(li.li_Catalog, MSG_UNKNOWN_JARL, "Unknown jarl"));
strcat(saystring, " (?-?)");
} else
{ saywho(JARL, counter, FALSE, FALSE);
strcat(saystring, "(");
stcl_d(numberstring, jarl[counter].strength);
strcat(saystring, numberstring);
strcat(saystring, "-");
stcl_d(numberstring, jarl[counter].moves);
strcat(saystring, numberstring);
strcat(saystring, ")");
}
say(UPPER);
} elif (*(countertype) == MONSTER)
{ strcpy(saystring, monstertypes[monster[counter].species]);
strcat(saystring, " ");
strcat(saystring, monster[counter].name);
strcat(saystring, " (");
stcl_d(numberstring, monster[counter].strength);
strcat(saystring, numberstring);
strcat(saystring, "-");
stcl_d(numberstring, monster[counter].moves);
strcat(saystring, numberstring);
strcat(saystring, ")");
say(UPPER);
} elif (*(countertype) == TREASURE)
{ strcpy(saystring, GetCatalogStr(li.li_Catalog, MSG_THE, "The"));
strcat(saystring, " ");
strcat(saystring, treasure[counter].name);
strcat(saystring, " ");
strcat(saystring, GetCatalogStr(li.li_Catalog, MSG_TREASURE2, "treasure"));
say(UPPER);
} elif (*(countertype) == SORD)
{ strcpy(saystring, GetCatalogStr(li.li_Catalog, MSG_SWORD, "Sword"));
strcat(saystring, " ");
strcat(saystring, sord[counter].name);
say(UPPER);
} }
break;
case IDCMP_VANILLAKEY:
if (code == ' ' && (mode != ANYKEY || tickspeed[speed] == -1))
{ return(-3);
} elif (code == 27) // Escape
{ if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
{ cleanexit(EXIT_SUCCESS);
} elif (mode != ANYKEY || tickspeed[speed] == -1)
{ return(-4);
} }
elif
( mode == MULTIKEYBOARD
|| mode == GLKEYBOARD
|| mode == YNKEYBOARD
|| mode == WRKEYBOARD
|| (mode == ANYKEY && tickspeed[speed] == -1)
)
{ code = toupper(code);
return((SLONG) code);
} elif (code == 8) // backspace
{ if (mode != ANYKEY || tickspeed[speed] == -1)
{ return(-2);
} }
break;
case IDCMP_RAWKEY:
switch(code)
{
case HELP:
if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
{ summarywindow();
} else
{ counter = checkcounters(mousex, mousey, countertype);
if (counter == -1)
{ country = checkcountry(mousex, mousey);
if (country >= 0)
{ infowindow(KINGDOM, country);
} else
{ summarywindow();
} }
else
{ infowindow(*(countertype), counter);
} }
break;
default:
if
( ( mode == MULTIKEYBOARD
|| (mode == ANYKEY && tickspeed[speed] == -1)
)
&& code < KEYUP
&& (code < FIRSTQUALIFIER || code > LASTQUALIFIER)
)
{ if (code == SCAN_F1 + cheat)
{ cheat++;
if (cheat == 5)
{ cheat = 0;
hero[BEOWULF].luck = 5000;
DisplayBeep(ScreenPtr);
} }
else cheat = 0;
}
break;
}
break;
case IDCMP_MENUPICK:
while (code != MENUNULL)
{ ItemPtr = ItemAddress(MenuPtr, code);
switch (MENUNUM(code))
{
case MN_PROJECT:
switch (ITEMNUM(code))
{
case IN_NEW:
return(-4);
case IN_SAVE:
savegame(FALSE);
break;
case IN_SAVEAS:
savegame(TRUE);
break;
case IN_QUIT:
cleanexit(EXIT_SUCCESS);
break;
default:
// IN_OPEN
break;
}
break;
case MN_SETTINGS:
switch(ITEMNUM(code))
{
case IN_SHOW_TITLEBAR:
if (ItemPtr->Flags & CHECKED)
{ titlebar = TRUE;
} else
{ titlebar = FALSE;
}
ShowTitle(ScreenPtr, titlebar);
break;
default:
break;
}
break;
case MN_HELP:
switch(ITEMNUM(code))
{
case IN_GAME_SUMMARY:
summarywindow();
break;
case IN_HELP_1:
docwindow(1);
break;
case IN_HELP_2:
docwindow(2);
break;
case IN_HELP_3:
docwindow(3);
break;
case IN_HELP_4:
docwindow(4);
break;
case IN_ABOUT:
helpabout();
break;
default:
break;
}
break;
default:
break;
}
code = ItemPtr->NextSelect;
}
break;
default: // IDCMP_MENUVERIFY, etc.
break;
} } } }
MODULE void newgame(void)
{ SLONG whichhero, whichjarl, whichmonster, whichcountry, whichslot,
whichtreasure, whichsord;
OffMenu(MainWindowPtr, FULLMENUNUM(MN_PROJECT, IN_NEW, NOSUB));
OffMenu(MainWindowPtr, FULLMENUNUM(MN_PROJECT, IN_OPEN, NOSUB));
OffMenu(MainWindowPtr, FULLMENUNUM(MN_PROJECT, IN_SAVE, NOSUB));
OffMenu(MainWindowPtr, FULLMENUNUM(MN_PROJECT, IN_SAVEAS, NOSUB));
OnMenu(MainWindowPtr, FULLMENUNUM(MN_HELP, IN_GAME_SUMMARY, NOSUB));
pathname[0] = 0;
/* 0. SET UP
"Divide the counters into four piles, keeping the heroes separate.
The four piles, all face down, should be: monsters of all sorts,
jarls, magic weapons [(swords)], and magic treasures.
Each player picks a hero counter to represent him or her in the game.
Players roll dice if two or more people want the same counter, and
high roll chooses first." */
reset_images();
for (whichhero = 0; whichhero <= HEROES; whichhero++)
{ hero[whichhero].strength = HERO_STRENGTH;
hero[whichhero].moves = HERO_MOVES;
hero[whichhero].name = trueheroname[whichhero];
hero[whichhero].attacking =
hero[whichhero].defending =
hero[whichhero].alive = FALSE;
hero[whichhero].verydead = TRUE;
hero[whichhero].glory =
hero[whichhero].luck =
hero[whichhero].wealth = 0;
hero[whichhero].rune = -1;
deselect_hero(whichhero, FALSE);
remove_hero(whichhero, FALSE);
}
for (whichjarl = 0; whichjarl <= JARLS; whichjarl++)
{ jarl[whichjarl].hero = -1;
jarl[whichjarl].wealth = 0;
jarl[whichjarl].attacking =
jarl[whichjarl].defending =
jarl[whichjarl].alive =
jarl[whichjarl].taken = FALSE;
deselect_jarl(whichjarl, FALSE);
remove_jarl(whichjarl, FALSE);
}
for (whichmonster = 0; whichmonster <= MONSTERS; whichmonster++)
{ monster[whichmonster].alive = FALSE;
monster[whichmonster].taken = FALSE;
deselect_monster(whichmonster, FALSE);
remove_monster(whichmonster, FALSE);
}
for (whichtreasure = 0; whichtreasure <= TREASURES; whichtreasure++)
{ remove_treasure(whichtreasure, FALSE);
treasure[whichtreasure].taken = FALSE;
treasure[whichtreasure].possessor =
treasure[whichtreasure].possessortype =
treasure[whichtreasure].where = -1;
}
for (whichsord = 0; whichsord <= SORDS; whichsord++)
{ remove_sord(whichsord, FALSE);
sord[whichsord].taken = FALSE;
sord[whichsord].possessor =
sord[whichsord].possessortype =
sord[whichsord].where = -1;
}
for (whichcountry = 0; whichcountry <= 65; whichcountry++)
{ world[whichcountry].hero = -1;
world[whichcountry].is = FALSE;
for (whichslot = 0; whichslot <= SLOTS; whichslot++)
{ world[whichcountry].slot[whichslot] = FALSE;
} }
screenoff();
SetRast(MainWindowPtr->RPort, BLACK);
darken();
drawmap();
screenon();
/* "Each player then picks a magic sword at random from the face-down
pile. Magic swords will not be given out again in the game and so all
of the left-over magic swords are put aside until the next game." */
for (whichhero = 0; whichhero <= HEROES; whichhero++)
{ if (hero[whichhero].control != NONE)
{ /* "Heroes begin the game in a randomly determined area (found in the
same manner as monsters are placed). This area should be noted on the
record sheet, as it is sometimes necessary to know a hero's home
country." */
newhero(whichhero, TRUE);
} }
place_monsters();
place_jarls();
refreshcounters();
turn = 1;
faxirides = 3;
}
MODULE void clearkybd(void)
{ struct IntuiMessage* MsgPtr;
while (MsgPtr = (struct IntuiMessage *) GT_GetIMsg(MainWindowPtr->UserPort))
GT_ReplyIMsg(MsgPtr);
}
MODULE void titlescreen(void)
{ AUTO FLAG done;
AUTO SLONG whichhero;
AUTO struct IntuiMessage* MsgPtr;
AUTO ULONG class;
AUTO UWORD code, qual;
AUTO struct Gadget* addr;
AUTO struct MenuItem* ItemPtr;
AUTO TEXT sgtext[40 + 1];
loaded =
gameover = FALSE;
OnMenu(MainWindowPtr, FULLMENUNUM(MN_PROJECT, IN_NEW, NOSUB));
OnMenu(MainWindowPtr, FULLMENUNUM(MN_PROJECT, IN_OPEN, NOSUB));
OffMenu(MainWindowPtr, FULLMENUNUM(MN_PROJECT, IN_SAVE, NOSUB));
OffMenu(MainWindowPtr, FULLMENUNUM(MN_PROJECT, IN_SAVEAS, NOSUB));
OffMenu(MainWindowPtr, FULLMENUNUM(MN_HELP, IN_GAME_SUMMARY, NOSUB));
SetWindowTitles(MainWindowPtr, (UBYTE *) -1, TITLEBAR); // this is not copied, it is a pointer
clearscreen();
drawlogo();
for (whichhero = 0; whichhero <= HEROES; whichhero++)
{ GT_SetGadgetAttrs(CycleGadgetPtr[whichhero], MainWindowPtr, NULL, GA_Disabled, FALSE, TAG_DONE);
}
GT_SetGadgetAttrs(SpeedGadgetPtr, MainWindowPtr, NULL, GA_Disabled, FALSE, TAG_DONE);
GT_SetGadgetAttrs(AdvancedGadgetPtr, MainWindowPtr, NULL, GA_Disabled, FALSE, TAG_DONE);
RefreshGadgets(GListPtr, MainWindowPtr, NULL);
SetDrMd(MainWindowPtr->RPort, JAM1);
for (whichhero = 0; whichhero <= HEROES; whichhero++)
{ SetAPen(MainWindowPtr->RPort, BLACK);
Move(MainWindowPtr->RPort, 212 + 1, 208 + TBSIZE + (whichhero * 13) + 1);
Text(MainWindowPtr->RPort, cycleheroname[whichhero], 10);
Move(MainWindowPtr->RPort, 212 + 1 + (cycleheropos[whichhero] * 8), 208 + TBSIZE + (whichhero * 13) + 1 + 1);
Text(MainWindowPtr->RPort, "_", 1);
if (DisplayDepth >= DEPTH)
{ SetAPen(MainWindowPtr->RPort, 136 + whichhero);
} else
{ SetAPen(MainWindowPtr->RPort, WHITE);
}
Move(MainWindowPtr->RPort, 212, 208 + TBSIZE + (whichhero * 13));
Text(MainWindowPtr->RPort, cycleheroname[whichhero], 10);
Move(MainWindowPtr->RPort, 212 + (cycleheropos[whichhero] * 8), 208 + TBSIZE + (whichhero * 13) + 1);
Text(MainWindowPtr->RPort, "_", 1);
}
strcpy(sgtext, GetCatalogStr(li.li_Catalog, MSG_MESSAGE_DELAY, "Message Delay:"));
SetAPen(MainWindowPtr->RPort, BLACK);
Move(MainWindowPtr->RPort, 292 - (strlen(sgtext) * 8) + 1, 305 + TBSIZE + 1);
Text(MainWindowPtr->RPort, sgtext, strlen(sgtext));
SetAPen(MainWindowPtr->RPort, WHITE);
Move(MainWindowPtr->RPort, 292 - (strlen(sgtext) * 8), 305 + TBSIZE);
Text(MainWindowPtr->RPort, sgtext, strlen(sgtext));
strcpy(sgtext, GetCatalogStr(li.li_Catalog, MSG_ADVANCED_MODE, "Advanced Mode?"));
SetAPen(MainWindowPtr->RPort, BLACK);
Move(MainWindowPtr->RPort, 292 - (strlen(sgtext) * 8) + 1, 329 + TBSIZE + 1);
Text(MainWindowPtr->RPort, sgtext, strlen(sgtext));
SetAPen(MainWindowPtr->RPort, WHITE);
Move(MainWindowPtr->RPort, 292 - (strlen(sgtext) * 8), 329 + TBSIZE);
Text(MainWindowPtr->RPort, sgtext, strlen(sgtext));
if (cliload)
{ if (loadgame(FALSE))
{ loaded = TRUE;
} else
{ cliload = FALSE;
} }
if (!cliload)
{ done = FALSE;
do
{ Wait(1L << MainWindowPtr->UserPort->mp_SigBit);
while (MsgPtr = (struct IntuiMessage *) GT_GetIMsg(MainWindowPtr->UserPort))
{ addr = (struct Gadget *) MsgPtr->IAddress;
class = MsgPtr->Class;
code = MsgPtr->Code;
qual = MsgPtr->Qualifier;
GT_ReplyIMsg(MsgPtr);
switch (class)
{
case IDCMP_RAWKEY:
if (!(qual & IEQUALIFIER_REPEAT))
{ switch (code)
{
case SCAN_F1:
cycle(0, qual);
break;
case SCAN_F2:
cycle(1, qual);
break;
case SCAN_F3:
cycle(2, qual);
break;
case SCAN_F4:
cycle(3, qual);
break;
case SCAN_F5:
cycle(4, qual);
break;
case SCAN_F6:
cycle(5, qual);
break;
case HELP:
helpabout();
break;
case SCAN_LEFT:
if (speed > 0)
{ if
( (qual & IEQUALIFIER_LSHIFT)
|| (qual & IEQUALIFIER_RSHIFT)
|| (qual & IEQUALIFIER_LALT)
|| (qual & IEQUALIFIER_RALT)
|| (qual & IEQUALIFIER_CONTROL)
)
{ speed = 0;
} else speed--;
GT_SetGadgetAttrs(SpeedGadgetPtr, MainWindowPtr, NULL, GTSL_Level, speed, TAG_DONE);
}
break;
case SCAN_RIGHT:
if (speed < 6)
{ if
( (qual & IEQUALIFIER_LSHIFT)
|| (qual & IEQUALIFIER_RSHIFT)
|| (qual & IEQUALIFIER_LALT)
|| (qual & IEQUALIFIER_RALT)
|| (qual & IEQUALIFIER_CONTROL)
)
{ speed = 6;
} else speed++;
GT_SetGadgetAttrs(SpeedGadgetPtr, MainWindowPtr, NULL, GTSL_Level, speed, TAG_DONE);
}
break;
default:
break;
} }
break;
case IDCMP_VANILLAKEY:
code = toupper(code);
switch(code)
{
case ' ':
case 13: // Return or Enter
done = TRUE;
break;
case 27: // Escape
cleanexit(EXIT_SUCCESS);
break;
case '1':
case 'B':
case '!':
cycle(0, qual);
break;
case '2':
case 'U':
case '@':
cycle(1, qual);
break;
case '3':
case 'E':
case '#':
cycle(2, qual);
break;
case '4':
case 'R':
case '$':
cycle(3, qual);
break;
case '5':
case 'S':
case '%':
cycle(4, qual);
break;
case '6':
case 'T':
case '^':
cycle(5, qual);
break;
default:
break;
}
break;
case IDCMP_MENUPICK:
while (code != MENUNULL)
{ ItemPtr = ItemAddress(MenuPtr, code);
switch (MENUNUM(code))
{
case MN_PROJECT:
switch (ITEMNUM(code))
{
case IN_NEW:
done = TRUE;
break;
case IN_OPEN:
if (loadgame(TRUE))
{ done = TRUE;
loaded = TRUE;
}
break;
case IN_QUIT:
cleanexit(EXIT_SUCCESS);
break;
default:
// IN_SAVE, IN_SAVEAS
break;
}
break;
case MN_SETTINGS:
switch(ITEMNUM(code))
{
case IN_SHOW_TITLEBAR:
if (ItemPtr->Flags & CHECKED)
{ titlebar = TRUE;
} else
{ titlebar = FALSE;
}
ShowTitle(ScreenPtr, titlebar);
break;
default:
break;
}
break;
case MN_HELP:
switch(ITEMNUM(code))
{
case IN_HELP_1:
docwindow(1);
break;
case IN_HELP_2:
docwindow(2);
break;
case IN_HELP_3:
docwindow(3);
break;
case IN_HELP_4:
docwindow(4);
break;
case IN_ABOUT:
helpabout();
break;
default:
break;
}
break;
default:
break;
}
code = ItemPtr->NextSelect;
}
break;
case IDCMP_MOUSEBUTTONS:
if (code == SELECTDOWN && !(qual & IEQUALIFIER_REPEAT))
{ done = TRUE;
}
break;
case IDCMP_REFRESHWINDOW:
GT_BeginRefresh(MainWindowPtr);
GT_EndRefresh(MainWindowPtr, TRUE);
break;
case IDCMP_GADGETUP:
if (addr == SpeedGadgetPtr)
{ speed = code;
} elif (addr == AdvancedGadgetPtr)
{ if (AdvancedGadgetPtr->Flags & GFLG_SELECTED)
{ advanced = TRUE;
monsters = 30;
treasures = 5;
} else
{ advanced = FALSE;
monsters = 26;
treasures = 3;
} }
else
{ for (whichhero = 0; whichhero <= HEROES; whichhero++)
{ if (addr == CycleGadgetPtr[whichhero])
{ hero[whichhero].control = code;
break;
} } }
break;
case IDCMP_CLOSEWINDOW:
cleanexit(EXIT_SUCCESS);
break;
default:
; /* IDCMP_INTUITICKS */
break;
} }
if (done)
{ done = FALSE;
for (whichhero = 0; whichhero <= HEROES; whichhero++)
{ if (hero[whichhero].control != NONE)
{ done = TRUE;
break;
} }
if (!done)
{ ; // DisplayBeep(ScreenPtr); // no heroes active
} }
} while (!done);
}
cliload = FALSE;
if (!loaded)
{ for (whichhero = 0; whichhero <= HEROES; whichhero++)
{ GT_SetGadgetAttrs(CycleGadgetPtr[whichhero], MainWindowPtr, NULL, GA_Disabled, TRUE, TAG_DONE);
}
GT_SetGadgetAttrs(SpeedGadgetPtr, MainWindowPtr, NULL, GA_Disabled, TRUE, TAG_DONE);
GT_SetGadgetAttrs(AdvancedGadgetPtr, MainWindowPtr, NULL, GA_Disabled, TRUE, TAG_DONE);
} }
MODULE void helpabout(void)
{ SBYTE line;
FLAG done = FALSE;
ULONG class;
UWORD code, qual;
struct IntuiMessage* MsgPtr;
if (!(HelpWindowPtr = (struct Window *) OpenWindowTags(NULL,
WA_Left, (SCREENXPIXEL / 2) - (ABOUTXPIXEL / 2),
WA_Top, (SCREENYPIXEL / 2) - (ABOUTYPIXEL / 2),
WA_Width, ABOUTXPIXEL,
WA_Height, ABOUTYPIXEL,
WA_IDCMP, IDCMP_CLOSEWINDOW | IDCMP_RAWKEY,
WA_Title, abouttitle,
WA_Gadgets, NULL,
WA_CustomScreen, ScreenPtr,
WA_DragBar, TRUE,
WA_CloseGadget, TRUE,
WA_NoCareRefresh, TRUE,
WA_Activate, TRUE,
WA_GimmeZeroZero, TRUE,
TAG_DONE)))
{ DisplayAlert(AT_Recovery, "\0\20\20Saga: Can't open About... window!\0", 24);
cleanexit(EXIT_FAILURE);
} else
{ fillwindow(HelpWindowPtr);
SetDrMd(HelpWindowPtr->RPort, JAM1);
SetAPen(HelpWindowPtr->RPort, BLACK);
for (line = 0; line <= ABOUTLINES; line++)
{ Move(HelpWindowPtr->RPort, about[line].x + 1, about[line].y + 1);
Text(HelpWindowPtr->RPort, about[line].text, (SBYTE) strlen(about[line].text));
}
SetAPen(HelpWindowPtr->RPort, WHITE);
for (line = 0; line <= ABOUTLINES; line++)
{ Move(HelpWindowPtr->RPort, about[line].x, about[line].y);
Text(HelpWindowPtr->RPort, about[line].text, (SBYTE) strlen(about[line].text));
}
drawabout();
if (aga)
{ boingball();
}
while (!done)
{ if (aga)
{ DrawGels();
} else
{ Wait(1L << HelpWindowPtr->UserPort->mp_SigBit);
}
while (MsgPtr = (struct IntuiMessage *) GetMsg(HelpWindowPtr->UserPort))
{ class = MsgPtr->Class;
code = MsgPtr->Code;
qual = MsgPtr->Qualifier;
ReplyMsg((struct Message *) MsgPtr);
switch (class)
{
case IDCMP_CLOSEWINDOW:
done = TRUE;
break;
case IDCMP_RAWKEY:
if (!(qual & IEQUALIFIER_REPEAT) && code < KEYUP && (code < FIRSTQUALIFIER || code > LASTQUALIFIER))
{ if
( code == ESCAPE
&& ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
)
{ cleanexit(EXIT_SUCCESS);
} else
{ done = TRUE;
} }
break;
default:
break;
} } }
if (aga)
{ unboingball();
}
CloseWindow(HelpWindowPtr);
HelpWindowPtr = NULL;
clearkybd();
} }
MODULE void resettime(void)
{ struct timerequest* TimerIORequestPtr;
struct timeval timeval;
if (!(TimerIORequestPtr = (struct timerequest *) AllocVec(sizeof(struct timerequest), MEMF_PUBLIC | MEMF_CLEAR)))
{ DisplayAlert(AT_Recovery, "\0\20\20Saga: Out of memory!\0", 24);
cleanexit(EXIT_FAILURE);
}
if (OpenDevice(TIMERNAME, UNIT_MICROHZ, (struct IORequest *) TimerIORequestPtr, 0))
{ FreeVec(TimerIORequestPtr);
DisplayAlert(AT_Recovery, "\0\20\20Saga: Can't open timer.device!\0", 24);
cleanexit(EXIT_FAILURE);
}
TimerBase = (struct Library *) TimerIORequestPtr->tr_node.io_Device;
GetSysTime(&timeval);
srand((UWORD) timeval.tv_micro);
// no need to abort timer I/O requests, as we never send any
CloseDevice((struct IORequest *) TimerIORequestPtr);
FreeVec(TimerIORequestPtr);
}
MODULE FLAG loadgame(FLAG aslwindow)
{ SLONG offset = 12, whichhero, whichjarl, whichmonster, whichcountry,
whichslot, whichtreasure, whichsord;
TEXT newpathname[255];
BPTR FileHandle /* = NULL */ ;
FLAG ok;
if (aslwindow)
{ if
( AslRequestTags
( ASLRqPtr,
ASL_Hail, GetCatalogStr(li.li_Catalog, MSG_LOAD_GAME, "Load Game"),
ASL_FuncFlags, FILF_PATGAD,
TAG_DONE
)
&& *(ASLRqPtr->rf_File)
)
{ strcpy(newpathname, ASLRqPtr->rf_Dir);
AddPart(newpathname, ASLRqPtr->rf_File, 254);
ok = TRUE;
} else
{ ok = FALSE;
} }
else
{ ok = TRUE;
strcpy(newpathname, pathname);
}
if (ok)
{ strcpy(saystring, GetCatalogStr(li.li_Catalog, MSG_LOADING, "Loading"));
strcat(saystring, " ");
strcat(saystring, newpathname);
strcat(saystring, "...");
say(LOWER);
if (!(FileHandle = Open(newpathname, MODE_OLDFILE)))
{ strcpy(saystring, GetCatalogStr(li.li_Catalog, MSG_CANT_OPEN, "Can't open"));
strcat(saystring, " ");
strcat(saystring, newpathname);
strcat(saystring, " ");
strcat(saystring, GetCatalogStr(li.li_Catalog, MSG_FOR_READING, "for reading"));
strcat(saystring, "!");
say(LOWER);
return(FALSE);
}
// read file
if (Read(FileHandle, IOBuffer, SAVELENGTH) != SAVELENGTH)
{ Close(FileHandle);
// FileHandle = NULL;
strcpy(saystring, GetCatalogStr(li.li_Catalog, MSG_CANT_READ_FROM, "Can't read from"));
strcat(saystring, " ");
strcat(saystring, newpathname);
strcat(saystring, "!");
say(LOWER);
return(FALSE);
}
if (strcmp(IOBuffer, "SAGA 1.4 "))
{ Close(FileHandle);
// FileHandle = NULL;
strcpy(saystring, newpathname);
strcat(saystring, " ");
strcat(saystring, GetCatalogStr(li.li_Catalog, MSG_I_N_A_V_S_G_F, "is not a valid saved game file"));
strcat(saystring, "!");
say(LOWER);
return(FALSE);
}
turn = (SLONG) ((SBYTE) IOBuffer[10]);
faxirides = (SLONG) ((SBYTE) IOBuffer[11]);
for (whichhero = 0; whichhero <= HEROES; whichhero++)
{ hero[whichhero].control = (SLONG) ((SBYTE) IOBuffer[offset++] );
hero[whichhero].alive = (FLAG) ((SBYTE) IOBuffer[offset++] );
hero[whichhero].verydead = (FLAG) ((SBYTE) IOBuffer[offset++] );
hero[whichhero].moves = (SLONG) ((SBYTE) IOBuffer[offset++] );
hero[whichhero].god = (SLONG) ((SBYTE) IOBuffer[offset++] );
hero[whichhero].rune = (SLONG) ((SBYTE) IOBuffer[offset++] );
hero[whichhero].where = (SLONG) ((SBYTE) IOBuffer[offset++] );
hero[whichhero].homewhere = (SLONG) ((SBYTE) IOBuffer[offset++] );
hero[whichhero].promoted = (SLONG) ((SBYTE) IOBuffer[offset++] );
hero[whichhero].wounded = (FLAG) ((SBYTE) IOBuffer[offset++] );
hero[whichhero].wealth = (SLONG) ((IOBuffer[offset++] * 256) + IOBuffer[offset++]);
hero[whichhero].glory = (SLONG) ((IOBuffer[offset++] * 256) + IOBuffer[offset++]);
hero[whichhero].luck = (SLONG) ((IOBuffer[offset++] * 256) + IOBuffer[offset++]);
hero[whichhero].sea = (SLONG) ((SBYTE) IOBuffer[offset++]);
hero[whichhero].loseturn = (FLAG) ((SBYTE) IOBuffer[offset++]);
hero[whichhero].maidens = (SLONG) ((SBYTE) IOBuffer[offset++]);
}
for (whichjarl = 0; whichjarl <= JARLS; whichjarl++)
{ jarl[whichjarl].where = (SLONG) ((SBYTE) IOBuffer[offset++]);
jarl[whichjarl].homewhere = (SLONG) ((SBYTE) IOBuffer[offset++]);
jarl[whichjarl].face = (SLONG) ((SBYTE) IOBuffer[offset++]);
jarl[whichjarl].hero = (SLONG) ((SBYTE) IOBuffer[offset++]);
jarl[whichjarl].taken = (FLAG) ((SBYTE) IOBuffer[offset++]);
jarl[whichjarl].sea = (SLONG) ((SBYTE) IOBuffer[offset++]);
jarl[whichjarl].loseturn = (FLAG) ((SBYTE) IOBuffer[offset++]);
jarl[whichjarl].alive = (FLAG) ((SBYTE) IOBuffer[offset++]);
}
for (whichmonster = 0; whichmonster <= MONSTERS; whichmonster++)
{ monster[whichmonster].taken = (FLAG) ((SBYTE) IOBuffer[offset++]);
monster[whichmonster].alive = (FLAG) ((SBYTE) IOBuffer[offset++]);
monster[whichmonster].where = (SLONG) ((SBYTE) IOBuffer[offset++]);
monster[whichmonster].wealth = (SLONG) ((SBYTE) IOBuffer[offset++]);
monster[whichmonster].sea = (SLONG) ((SBYTE) IOBuffer[offset++]);
offset++; // skip monster[].loseturn
}
for (whichtreasure = 0; whichtreasure <= TREASURES; whichtreasure++)
{ treasure[whichtreasure].taken = (FLAG) ((SBYTE) IOBuffer[offset++]);
treasure[whichtreasure].possessor = (FLAG) ((SBYTE) IOBuffer[offset++]);
treasure[whichtreasure].possessortype = (SLONG) ((SBYTE) IOBuffer[offset++]);
treasure[whichtreasure].where = (SLONG) ((SBYTE) IOBuffer[offset++]);
}
for (whichsord = 0; whichsord <= SORDS; whichsord++)
{ sord[whichsord].taken = (FLAG) ((SBYTE) IOBuffer[offset++]);
sord[whichsord].possessor = (FLAG) ((SBYTE) IOBuffer[offset++]);
sord[whichsord].possessortype = (SLONG) ((SBYTE) IOBuffer[offset++]);
sord[whichsord].where = (SLONG) ((SBYTE) IOBuffer[offset++]);
}
for (whichcountry = 0; whichcountry <= 35; whichcountry++)
{ world[whichcountry].hero = (SLONG) ((SBYTE) IOBuffer[offset++]);
world[whichcountry].is = (FLAG) ((SBYTE) IOBuffer[offset++]);
}
advanced = (FLAG) ((SBYTE) IOBuffer[offset]); // ++ is not needed
// no need to read version string
Close(FileHandle);
// FileHandle = NULL;
strcpy(pathname, newpathname);
if (advanced)
{ treasures = 5;
monsters = 30;
} else
{ treasures = 3;
monsters = 26;
}
screenoff();
for (whichhero = 0; whichhero <= HEROES; whichhero++)
{ GT_SetGadgetAttrs(CycleGadgetPtr[whichhero], MainWindowPtr, NULL, GA_Disabled, TRUE, TAG_DONE);
}
GT_SetGadgetAttrs(SpeedGadgetPtr, MainWindowPtr, NULL, GA_Disabled, TRUE, TAG_DONE);
GT_SetGadgetAttrs(AdvancedGadgetPtr, MainWindowPtr, NULL, GA_Disabled, TRUE, TAG_DONE);
screenon();
for (whichcountry = 0; whichcountry <= 65; whichcountry++)
{ for (whichslot = 0; whichslot <= SLOTS; whichslot++)
{ world[whichcountry].slot[whichslot] = FALSE;
} }
for (whichhero = 0; whichhero <= HEROES; whichhero++)
{ if (hero[whichhero].promoted == -1)
{ hero[whichhero].name = trueheroname[whichhero];
hero[whichhero].strength = HERO_STRENGTH;
hero[whichhero].moves = HERO_MOVES;
} else
{ hero[whichhero].name = jarl[hero[whichhero].promoted].name;
hero[whichhero].strength = jarl[hero[whichhero].promoted].strength;
hero[whichhero].moves = jarl[hero[whichhero].promoted].moves;
}
deselect_hero(whichhero, FALSE);
if (hero[whichhero].alive)
{ move_hero(whichhero, FALSE);
} else
{ remove_hero(whichhero, FALSE);
} }
for (whichjarl = 0; whichjarl <= JARLS; whichjarl++)
{ jarl[whichjarl].recruitable = FALSE;
if (jarl[whichjarl].alive)
{ if (jarl[whichjarl].face == FACEUP)
{ revealjarl(whichjarl, FALSE);
} else
{ assert(jarl[whichjarl].face == FACEDOWN);
hidejarl(whichjarl, FALSE);
}
move_jarl(whichjarl, FALSE);
} else
{ remove_jarl(whichjarl, FALSE);
} }
for (whichmonster = 0; whichmonster <= MONSTERS; whichmonster++)
{ if (monster[whichmonster].alive)
{ move_monster(whichmonster, FALSE);
} else
{ remove_monster(whichmonster, FALSE);
} }
for (whichtreasure = 0; whichtreasure <= TREASURES; whichtreasure++)
{ if (treasure[whichtreasure].possessor == -1)
{ move_treasure(whichtreasure, FALSE);
} }
for (whichsord = 0; whichsord <= SORDS; whichsord++)
{ if (sord[whichsord].possessor == -1)
{ move_sord(whichsord, FALSE);
} }
SetRast(MainWindowPtr->RPort, BLACK);
darken();
drawmap();
refreshcounters();
if (faxirides == -1)
{ faxirides = 0;
treasure_disappear(FREYFAXI);
}
OffMenu(MainWindowPtr, FULLMENUNUM(MN_PROJECT, IN_NEW, NOSUB));
OffMenu(MainWindowPtr, FULLMENUNUM(MN_PROJECT, IN_OPEN, NOSUB));
OffMenu(MainWindowPtr, FULLMENUNUM(MN_PROJECT, IN_SAVE, NOSUB));
OffMenu(MainWindowPtr, FULLMENUNUM(MN_PROJECT, IN_SAVEAS, NOSUB));
OnMenu(MainWindowPtr, FULLMENUNUM(MN_HELP, IN_GAME_SUMMARY, NOSUB));
strcpy(saystring, GetCatalogStr(li.li_Catalog, MSG_LOADED, "Loaded"));
strcat(saystring, " ");
strcat(saystring, pathname);
strcat(saystring, ".");
say(LOWER);
return(TRUE);
} }
MODULE void savegame(FLAG saveas)
{ SLONG offset = 12, whichhero, whichjarl, whichmonster, whichcountry,
whichtreasure, whichsord;
FLAG cont = TRUE;
TEXT newpathname[255];
BPTR FileHandle /* = NULL */ ;
strcpy(newpathname, pathname);
if (saveas || newpathname[0] == 0)
{ if
( AslRequestTags
( ASLRqPtr,
ASL_Hail, GetCatalogStr(li.li_Catalog, MSG_SAVE_GAME, "Save Game"),
ASL_FuncFlags, FILF_PATGAD | FILF_SAVE,
TAG_DONE
)
&& *(ASLRqPtr->rf_File) != 0
)
{ strcpy(newpathname, ASLRqPtr->rf_Dir);
AddPart(newpathname, ASLRqPtr->rf_File, 254);
} else
{ cont = FALSE;
} }
if (!cont)
{ return;
}
strcpy(saystring, GetCatalogStr(li.li_Catalog, MSG_SAVING, "Saving"));
strcat(saystring, " ");
strcat(saystring, newpathname);
strcat(saystring, "...");
say(LOWER);
if (!(FileHandle = Open(newpathname, MODE_NEWFILE)))
{ strcpy(saystring, GetCatalogStr(li.li_Catalog, MSG_CANT_OPEN, "Can't open"));
strcat(saystring, " ");
strcat(saystring, newpathname);
strcat(saystring, " ");
strcat(saystring, GetCatalogStr(li.li_Catalog, MSG_FOR_WRITING, "for writing"));
strcat(saystring, "!");
say(LOWER);
anykey();
return;
}
/* write header
SAGA 1.4 *#%
012345678901
where * is NULL byte and # is turn and % is faxi rides */
strcpy(IOBuffer, "SAGA 1.4 ");
IOBuffer[10] = (SBYTE) turn;
IOBuffer[11] = (SBYTE) faxirides;
for (whichhero = 0; whichhero <= HEROES; whichhero++)
{ IOBuffer[offset++] = (SBYTE) hero[whichhero].control;
IOBuffer[offset++] = (SBYTE) hero[whichhero].alive;
IOBuffer[offset++] = (SBYTE) hero[whichhero].verydead;
IOBuffer[offset++] = (SBYTE) hero[whichhero].moves;
IOBuffer[offset++] = (SBYTE) hero[whichhero].god;
IOBuffer[offset++] = (SBYTE) hero[whichhero].rune;
IOBuffer[offset++] = (SBYTE) hero[whichhero].where;
IOBuffer[offset++] = (SBYTE) hero[whichhero].homewhere;
IOBuffer[offset++] = (SBYTE) hero[whichhero].promoted;
IOBuffer[offset++] = (SBYTE) hero[whichhero].wounded;
IOBuffer[offset++] = (UBYTE) (hero[whichhero].wealth / 256);
IOBuffer[offset++] = (UBYTE) (hero[whichhero].wealth % 256);
IOBuffer[offset++] = (UBYTE) (hero[whichhero].glory / 256);
IOBuffer[offset++] = (UBYTE) (hero[whichhero].glory % 256);
IOBuffer[offset++] = (UBYTE) (hero[whichhero].luck / 256);
IOBuffer[offset++] = (UBYTE) (hero[whichhero].luck % 256);
IOBuffer[offset++] = (SBYTE) hero[whichhero].sea;
IOBuffer[offset++] = (SBYTE) hero[whichhero].loseturn;
IOBuffer[offset++] = (SBYTE) hero[whichhero].maidens;
}
for (whichjarl = 0; whichjarl <= JARLS; whichjarl++)
{ IOBuffer[offset++] = (SBYTE) jarl[whichjarl].where;
IOBuffer[offset++] = (SBYTE) jarl[whichjarl].homewhere;
IOBuffer[offset++] = (SBYTE) jarl[whichjarl].face;
IOBuffer[offset++] = (SBYTE) jarl[whichjarl].hero;
IOBuffer[offset++] = (SBYTE) jarl[whichjarl].taken;
IOBuffer[offset++] = (SBYTE) jarl[whichjarl].sea;
IOBuffer[offset++] = (SBYTE) jarl[whichjarl].loseturn;
IOBuffer[offset++] = (SBYTE) jarl[whichjarl].alive;
}
for (whichmonster = 0; whichmonster <= MONSTERS; whichmonster++)
{ IOBuffer[offset++] = (SBYTE) monster[whichmonster].taken;
IOBuffer[offset++] = (SBYTE) monster[whichmonster].alive;
IOBuffer[offset++] = (SBYTE) monster[whichmonster].where;
IOBuffer[offset++] = (SBYTE) monster[whichmonster].wealth;
IOBuffer[offset++] = (SBYTE) monster[whichmonster].sea;
IOBuffer[offset++] = (SBYTE) 0; // skip monster loseturn
}
for (whichtreasure = 0; whichtreasure <= TREASURES; whichtreasure++)
{ IOBuffer[offset++] = (SBYTE) treasure[whichtreasure].taken;
IOBuffer[offset++] = (SBYTE) treasure[whichtreasure].possessor;
IOBuffer[offset++] = (SBYTE) treasure[whichtreasure].possessortype;
IOBuffer[offset++] = (SBYTE) treasure[whichtreasure].where;
}
for (whichsord = 0; whichsord <= SORDS; whichsord++)
{ IOBuffer[offset++] = (SBYTE) sord[whichsord].taken;
IOBuffer[offset++] = (SBYTE) sord[whichsord].possessor;
IOBuffer[offset++] = (SBYTE) sord[whichsord].possessortype;
IOBuffer[offset++] = (SBYTE) sord[whichsord].where;
}
for (whichcountry = 0; whichcountry <= 35; whichcountry++)
{ IOBuffer[offset++] = (SBYTE) world[whichcountry].hero;
IOBuffer[offset++] = (SBYTE) world[whichcountry].is;
}
IOBuffer[offset++] = (SBYTE) advanced;
#ifdef EXTRAVERBOSE
Printf("%ld bytes written.\n", offset);
#endif
if (Write(FileHandle, IOBuffer, offset) != offset)
{ Close(FileHandle);
// FileHandle = NULL;
strcpy(saystring, GetCatalogStr(li.li_Catalog, MSG_CANT_WRITE_TO, "Can't write to"));
strcat(saystring, " ");
strcat(saystring, newpathname);
strcat(saystring, "!");
say(LOWER);
anykey();
return;
}
/* write version string */
Write(FileHandle, VERSION, strlen(VERSION));
Close(FileHandle);
// FileHandle = NULL;
strcpy(pathname, newpathname);
strcpy(saystring, GetCatalogStr(li.li_Catalog, MSG_SAVED, "Saved"));
strcat(saystring, " ");
strcat(saystring, pathname);
strcat(saystring, ".");
say(LOWER);
// no need for anykey(), as there is one when we return anyway.
}
EXPORT void darken(void)
{ SLONG whichcountry, colour;
for (whichcountry = 0; whichcountry <= 35; whichcountry++)
{ if (whichcountry >= 9 && whichcountry <= 11)
{ colour = whichcountry + 80;
} else
{ colour = whichcountry + 8;
}
if (world[whichcountry].is)
{ SetRGB4(&ScreenPtr->ViewPort, colour, 12, 12, 12); // light grey ice
} elif (world[whichcountry].hero != -1)
{ SetRGB4
( &ScreenPtr->ViewPort,
colour,
herocolour[world[whichcountry].hero].red,
herocolour[world[whichcountry].hero].green,
herocolour[world[whichcountry].hero].blue
);
} else
{ SetRGB4
( &ScreenPtr->ViewPort,
colour,
taxcolours[world[whichcountry].tax].red,
taxcolours[world[whichcountry].tax].green,
taxcolours[world[whichcountry].tax].blue
);
} } }
MODULE SLONG checkcountry(WORD mousex, WORD mousey)
{ SLONG country;
country = ReadPixel(MainWindowPtr->RPort, mousex, mousey);
if (country == 80 || country == 81 || country == 91)
{ country = 11; // Scandia
} elif (country == 82 || country == 83)
{ country = 30; // Pictland
} elif (country == 84 || country == 85)
{ country = 31; // Hebrides
} elif (country == 89)
{ country = 9; // Suder Gotland
} elif (country == 90)
{ country = 10; // Juteland
} else
{ country -= 8;
}
return(country);
}
MODULE void infowindow(SLONG countertype, SLONG whichcounter)
{ SLONG lines,
leftlines = 0,
rightlines = 0,
oldwhichline,
whichline,
whichcountry,
whichjarl,
whichhero,
whichtreasure,
whichsord,
wide,
whichmonster;
FLAG counterrow = FALSE,
ok;
if (countertype == HERO)
{ sprintf(label[0], "%s:", GetCatalogStr(li.li_Catalog, MSG_HERO_NAME, "Hero Name" ));
sprintf(label[1], "%s:", GetCatalogStr(li.li_Catalog, MSG_CONTROL, "Control" ));
sprintf(label[2], "%s:", GetCatalogStr(li.li_Catalog, MSG_COMBAT_STRENGTH, "Combat Strength"));
sprintf(label[3], "%s:", GetCatalogStr(li.li_Catalog, MSG_MOVEMENT_FACTOR, "Movement Factor"));
sprintf(label[4], "%s:", GetCatalogStr(li.li_Catalog, MSG_GLORY, "Glory" ));
sprintf(label[5], "%s:", GetCatalogStr(li.li_Catalog, MSG_LUCK, "Luck" ));
sprintf(label[6], "%s:", GetCatalogStr(li.li_Catalog, MSG_WEALTH, "Wealth" ));
sprintf(label[8], "%s:", GetCatalogStr(li.li_Catalog, MSG_HOMELAND, "Homeland" ));
sprintf(label[9], "%s:", GetCatalogStr(li.li_Catalog, MSG_MAIDENS, "Maidens" ));
sprintf(label[10], "%s:", GetCatalogStr(li.li_Catalog, MSG_RUNE, "Rune" ));
sprintf(label[11], "%s:", GetCatalogStr(li.li_Catalog, MSG_SWORD, "Sword" ));
sprintf(label[12], "%s:", GetCatalogStr(li.li_Catalog, MSG_STATUS, "Status" ));
sprintf(label[13], "%s:", GetCatalogStr(li.li_Catalog, MSG_GOD, "God" ));
/* If labels beyond [13] are desired, the labels[] array will of
course to be redimensioned. */
strcpy(line[LEFTSIDE][0], hero[whichcounter].name);
if (hero[whichcounter].control == HUMAN)
{ strcpy(line[LEFTSIDE][1], GetCatalogStr(li.li_Catalog, MSG_HUMAN, "Human"));
} else
{ assert(hero[whichcounter].control == AMIGA);
strcpy(line[LEFTSIDE][1], "Amiga");
}
sprintf
( line[LEFTSIDE][2], "%ld (%ld/%ld)",
hero[whichcounter].strength,
getstrength(HERO, whichcounter, FALSE),
getstrength(HERO, whichcounter, TRUE)
);
sprintf
( line[LEFTSIDE][3], "%ld (%ld)",
hero[whichcounter].moves,
getusualmoves(HERO, whichcounter)
);
sprintf(line[LEFTSIDE][4], "%ld", hero[whichcounter].glory);
sprintf(line[LEFTSIDE][5], "%ld", hero[whichcounter].luck);
sprintf(line[LEFTSIDE][6], "%ld", hero[whichcounter].wealth);
print_location(hero[whichcounter].where, 7);
sprintf
( line[LEFTSIDE][8], "%s (%ld)",
world[hero[whichcounter].homewhere].name,
world[hero[whichcounter].homewhere].tax
);
sprintf(line[LEFTSIDE][9], "%ld", hero[whichcounter].maidens);
if (hero[whichcounter].rune == -1)
{ strcpy(line[LEFTSIDE][10], GetCatalogStr(li.li_Catalog, MSG_NONE, "None"));
} else
{ strcpy(line[LEFTSIDE][10], rune[hero[whichcounter].rune].name);
}
ok = FALSE;
for (whichsord = 0; whichsord <= SORDS; whichsord++)
{ if
( sord[whichsord].possessortype == HERO
&& sord[whichsord].possessor == whichcounter
)
{ ok = TRUE;
counterrow = TRUE;
strcpy(line[LEFTSIDE][11], sord[whichsord].name);
break; // for speed
} }
if (!ok)
{ strcpy(line[LEFTSIDE][11], GetCatalogStr(li.li_Catalog, MSG_NONE, "None"));
}
if (!hero[whichcounter].wounded)
{ strcpy(line[LEFTSIDE][12], GetCatalogStr(li.li_Catalog, MSG_HEALTHY, "Healthy"));
} else
{ strcpy(line[LEFTSIDE][12], GetCatalogStr(li.li_Catalog, MSG_WOUNDED, "Wounded"));
}
switch (hero[whichcounter].god)
{
case ODIN:
strcpy(line[LEFTSIDE][13], "Odin");
break;
case THOR:
strcpy(line[LEFTSIDE][13], "Thor");
break;
case TYR:
strcpy(line[LEFTSIDE][13], "Tyr");
break;
default:
strcpy(line[LEFTSIDE][13], GetCatalogStr(li.li_Catalog, MSG_NONE, "None"));
break;
}
print_paralyzed(hero[whichcounter].loseturn, 14);
print_hagall(hero[whichcounter].hagall, 15);
print_sea(hero[whichcounter].sea, 16);
print_routed(hero[whichcounter].routed, 17);
leftlines = 18; // counting from 1
strcpy(line[RIGHTSIDE][0], GetCatalogStr(li.li_Catalog, MSG_RECRUITED_JARLS, "Recruited Jarls"));
strcat(line[RIGHTSIDE][0], ":");
whichline = oldwhichline = 1; // whichline always points to the NEXT line.
for (whichjarl = 0; whichjarl <= JARLS; whichjarl++)
{ if (jarl[whichjarl].alive && jarl[whichjarl].hero == whichcounter)
{ strcpy(line[RIGHTSIDE][whichline], " ");
strcat(line[RIGHTSIDE][whichline], jarl[whichjarl].name);
strcat(line[RIGHTSIDE][whichline], " (");
stcl_d(numberstring, jarl[whichjarl].strength);
strcat(line[RIGHTSIDE][whichline], numberstring);
strcat(line[RIGHTSIDE][whichline], "-");
stcl_d(numberstring, jarl[whichjarl].moves);
strcat(line[RIGHTSIDE][whichline], numberstring);
strcat(line[RIGHTSIDE][whichline], ")");
whichline++;
} }
if (whichline == oldwhichline)
{ strcpy(line[RIGHTSIDE][whichline], " ");
strcat(line[RIGHTSIDE][whichline], GetCatalogStr(li.li_Catalog, MSG_NONE, "None"));
whichline++;
}
strcpy(line[RIGHTSIDE][whichline], "");
whichline++;
strcpy(line[RIGHTSIDE][whichline], GetCatalogStr(li.li_Catalog, MSG_CONQUERED_KINGDOMS, "Conquered Kingdoms"));
strcat(line[RIGHTSIDE][whichline], ":");
whichline++;
oldwhichline = whichline;
for (whichcountry = 0; whichcountry <= 35; whichcountry++)
{ if (world[whichcountry].hero == whichcounter)
{ strcpy(line[RIGHTSIDE][whichline], " ");
strcat(line[RIGHTSIDE][whichline], world[whichcountry].name);
strcat(line[RIGHTSIDE][whichline], " (");
stcl_d(numberstring, world[whichcountry].tax);
strcat(line[RIGHTSIDE][whichline], numberstring);
strcat(line[RIGHTSIDE][whichline], ")");
whichline++;
} }
if (whichline == oldwhichline)
{ strcpy(line[RIGHTSIDE][whichline], " ");
strcat(line[RIGHTSIDE][whichline], GetCatalogStr(li.li_Catalog, MSG_NONE, "None"));
whichline++;
}
strcpy(line[RIGHTSIDE][whichline], "");
whichline++;
strcpy(line[RIGHTSIDE][whichline], GetCatalogStr(li.li_Catalog, MSG_MAGIC_TREASURES, "Magic Treasures"));
strcat(line[RIGHTSIDE][whichline], ":");
whichline++;
oldwhichline = whichline;
for (whichtreasure = 0; whichtreasure <= TREASURES; whichtreasure++)
{ if (treasure[whichtreasure].possessortype == HERO
&& treasure[whichtreasure].possessor == whichcounter
)
{ counterrow = TRUE;
strcpy(line[RIGHTSIDE][whichline], " ");
strcat(line[RIGHTSIDE][whichline], treasure[whichtreasure].name);
if (whichtreasure == FREYFAXI)
{ strcat(line[RIGHTSIDE][whichline], " (");
stcl_d(numberstring, faxirides);
strcat(line[RIGHTSIDE][whichline], numberstring);
strcat(line[RIGHTSIDE][whichline], " ");
if (faxirides != 1)
{ strcat(line[RIGHTSIDE][whichline], GetCatalogStr(li.li_Catalog, MSG_RIDES2, "rides"));
} else
{ strcat(line[RIGHTSIDE][whichline], GetCatalogStr(li.li_Catalog, MSG_RIDE, "ride"));
}
strcat(line[RIGHTSIDE][whichline], ")");
}
whichline++;
} }
if (whichline == oldwhichline)
{ strcpy(line[RIGHTSIDE][whichline], " ");
strcat(line[RIGHTSIDE][whichline], GetCatalogStr(li.li_Catalog, MSG_NONE, "None"));
whichline++;
}
rightlines = whichline;
} elif (countertype == MONSTER)
{ sprintf(label[0], "%s:", GetCatalogStr(li.li_Catalog, MSG_MONSTER_NAME, "Monster Name" ));
sprintf(label[1], "%s:", GetCatalogStr(li.li_Catalog, MSG_MONSTER_SPECIES, "Monster Species"));
sprintf(label[2], "%s:", GetCatalogStr(li.li_Catalog, MSG_COMBAT_STRENGTH, "Combat Strength"));
sprintf(label[3], "%s:", GetCatalogStr(li.li_Catalog, MSG_MOVEMENT_FACTOR, "Movement Factor"));
sprintf(label[4], "%s:", GetCatalogStr(li.li_Catalog, MSG_WEALTH, "Wealth" ));
sprintf(label[8], "%s?", GetCatalogStr(li.li_Catalog, MSG_TREASURE, "Treasure" ));
strcpy(line[LEFTSIDE][0], monster[whichcounter].name);
strcpy(line[LEFTSIDE][1], monstertypes[monster[whichcounter].species]);
sprintf
( line[LEFTSIDE][2],
"%ld (%ld/%ld)",
monster[whichcounter].strength,
getstrength(MONSTER, whichcounter, FALSE),
getstrength(MONSTER, whichcounter, TRUE)
);
sprintf
( line[LEFTSIDE][3],
"%ld (%ld)",
monster[whichcounter].moves,
getusualmoves(MONSTER, whichcounter)
);
sprintf(line[LEFTSIDE][4], "%ld", monster[whichcounter].wealth);
print_location(monster[whichcounter].where, 5);
print_hagall(monster[whichcounter].hagall, 6);
print_sea(monster[whichcounter].sea, 7);
ok = FALSE;
for (whichtreasure = 0; whichtreasure <= TREASURES; whichtreasure++)
{ if
( treasure[whichtreasure].possessortype == MONSTER
&& treasure[whichtreasure].possessor == whichcounter
)
{ ok = TRUE;
break;
} }
if (ok)
{ strcpy(line[LEFTSIDE][8], GetCatalogStr(li.li_Catalog, MSG_YES, "Yes"));
} else
{ strcpy(line[LEFTSIDE][8], GetCatalogStr(li.li_Catalog, MSG_NO, "No"));
}
leftlines = 9; // counting from 1
rightlines = 0;
} elif (countertype == JARL)
{ sprintf(label[0], "%s:", GetCatalogStr(li.li_Catalog, MSG_JARL_NAME, "Jarl Name" ));
sprintf(label[1], "%s:", GetCatalogStr(li.li_Catalog, MSG_HERO, "Hero" ));
sprintf(label[2], "%s:", GetCatalogStr(li.li_Catalog, MSG_COMBAT_STRENGTH, "Combat Strength"));
sprintf(label[3], "%s:", GetCatalogStr(li.li_Catalog, MSG_MOVEMENT_FACTOR, "Movement Factor"));
sprintf(label[4], "%s:", GetCatalogStr(li.li_Catalog, MSG_WEALTH, "Wealth" ));
sprintf(label[6], "%s:", GetCatalogStr(li.li_Catalog, MSG_HOMELAND, "Homeland" ));
sprintf(label[7], "%s:", GetCatalogStr(li.li_Catalog, MSG_SWORD, "Sword" ));
if (jarl[whichcounter].face == FACEUP)
{ strcpy(line[LEFTSIDE][0], jarl[whichcounter].name);
} else
{ strcpy(line[LEFTSIDE][0], GetCatalogStr(li.li_Catalog, MSG_UNKNOWN, "Unknown"));
}
if (jarl[whichcounter].hero == -1)
{ strcpy(line[LEFTSIDE][1], GetCatalogStr(li.li_Catalog, MSG_KING_NONE, "None"));
} else
{ strcpy(line[LEFTSIDE][1], hero[jarl[whichcounter].hero].name);
}
if (jarl[whichcounter].face == FACEUP)
{ sprintf
( line[LEFTSIDE][2], "%ld (%ld/%ld)",
jarl[whichcounter].strength,
getstrength(JARL, whichcounter, FALSE),
getstrength(JARL, whichcounter, TRUE)
);
} else
{ assert(jarl[whichcounter].face == FACEDOWN);
strcpy(line[LEFTSIDE][2], GetCatalogStr(li.li_Catalog, MSG_UNKNOWN, "Unknown"));
}
if (jarl[whichcounter].face == FACEUP)
{ sprintf
( line[LEFTSIDE][3], "%ld (%ld)",
jarl[whichcounter].moves,
getusualmoves(JARL, whichcounter)
);
} else
{ assert(jarl[whichcounter].face == FACEDOWN);
strcat(line[LEFTSIDE][3], GetCatalogStr(li.li_Catalog, MSG_UNKNOWN, "Unknown"));
}
sprintf(line[LEFTSIDE][4], "%ld", jarl[whichcounter].wealth);
print_location(jarl[whichcounter].where, 5);
sprintf
( line[LEFTSIDE][6], "%s (%ld)",
world[jarl[whichcounter].homewhere].name,
world[jarl[whichcounter].homewhere].tax
);
ok = FALSE;
for (whichsord = 0; whichsord <= SORDS; whichsord++)
{ if
( sord[whichsord].possessortype == JARL
&& sord[whichsord].possessor == whichcounter
)
{ ok = TRUE;
counterrow = TRUE;
strcpy(line[LEFTSIDE][7], sord[whichsord].name);
break; // for speed
} }
if (!ok)
{ strcpy(line[LEFTSIDE][7], GetCatalogStr(li.li_Catalog, MSG_NONE, "None"));
}
print_paralyzed(jarl[whichcounter].loseturn, 8);
print_hagall(jarl[whichcounter].hagall, 9);
print_sea(jarl[whichcounter].sea, 10);
print_routed(jarl[whichcounter].routed, 11);
leftlines = 12; // counting from 1
strcpy(line[RIGHTSIDE][0], GetCatalogStr(li.li_Catalog, MSG_MAGIC_TREASURES, "Magic Treasures"));
strcat(line[RIGHTSIDE][0], ":");
whichline = oldwhichline = 1; // whichline always points to the NEXT line.
for (whichtreasure = 0; whichtreasure <= TREASURES; whichtreasure++)
{ if (treasure[whichtreasure].possessortype == JARL
&& treasure[whichtreasure].possessor == whichcounter
)
{ counterrow = TRUE;
strcpy(line[RIGHTSIDE][whichline], " ");
strcat(line[RIGHTSIDE][whichline], treasure[whichtreasure].name);
if (whichtreasure == FREYFAXI)
{ strcat(line[RIGHTSIDE][whichline], " (");
stcl_d(numberstring, faxirides);
strcat(line[RIGHTSIDE][whichline], numberstring);
strcat(line[RIGHTSIDE][whichline], " ");
strcat(line[RIGHTSIDE][whichline], GetCatalogStr(li.li_Catalog, MSG_RIDES2, "rides"));
strcat(line[RIGHTSIDE][whichline], ")");
}
whichline++;
} }
if (whichline == oldwhichline)
{ strcpy(line[RIGHTSIDE][whichline], " ");
strcat(line[RIGHTSIDE][whichline], GetCatalogStr(li.li_Catalog, MSG_NONE, "None"));
whichline++;
}
rightlines = whichline;
} elif (countertype == TREASURE)
{ strcpy(line[LEFTSIDE][0], GetCatalogStr(li.li_Catalog, MSG_TREASURE_NAME, "Treasure Name"));
strcat(line[LEFTSIDE][0], ":");
pad(line[LEFTSIDE][0]);
strcat(line[LEFTSIDE][0], treasure[whichcounter].name);
strcpy(line[LEFTSIDE][1], GetCatalogStr(li.li_Catalog, MSG_LOCATION, "Location"));
strcat(line[LEFTSIDE][1], ":");
pad(line[LEFTSIDE][1]);
strcat(line[LEFTSIDE][1], world[treasure[whichcounter].where].name);
strcpy(line[LEFTSIDE][2], GetCatalogStr(li.li_Catalog, MSG_RIDES, "Rides"));
strcat(line[LEFTSIDE][2], ":");
pad(line[LEFTSIDE][2]);
if (whichcounter == FREYFAXI)
{ assert(faxirides != -1);
stcl_d(numberstring, faxirides);
strcat(line[LEFTSIDE][2], numberstring);
} else
{ strcat(line[LEFTSIDE][2], GetCatalogStr(li.li_Catalog, MSG_N_A, "n/a"));
}
line[LEFTSIDE][3][0] = 0; // blank line
switch (whichcounter)
{
case BROSUNGNECKLACE:
strcpy(line[LEFTSIDE][4], GetCatalogStr(li.li_Catalog, MSG_NECKLACE_1, "This treasure is worth 20 marks. It may" ));
strcpy(line[LEFTSIDE][5], GetCatalogStr(li.li_Catalog, MSG_NECKLACE_2, "be traded for any item in a dragon's" ));
strcpy(line[LEFTSIDE][6], GetCatalogStr(li.li_Catalog, MSG_NECKLACE_3, "hoard. The wearer moves into the area" ));
strcpy(line[LEFTSIDE][7], GetCatalogStr(li.li_Catalog, MSG_NECKLACE_4, "adjacent to that of the dragon, and gives"));
strcpy(line[LEFTSIDE][8], GetCatalogStr(li.li_Catalog, MSG_NECKLACE_5, "it to the dragon while taking what the" ));
strcpy(line[LEFTSIDE][9], GetCatalogStr(li.li_Catalog, MSG_NECKLACE_6, "dragon had. The wearer may then see what" ));
strcpy(line[LEFTSIDE][10], GetCatalogStr(li.li_Catalog, MSG_NECKLACE_7, "he had traded for." ));
leftlines = 11;
break;
case FREYFAXI:
strcpy(line[LEFTSIDE][4], GetCatalogStr(li.li_Catalog, MSG_FAXI_1, "This treasure is a magic horse that can" ));
strcpy(line[LEFTSIDE][5], GetCatalogStr(li.li_Catalog, MSG_FAXI_2, "be ridden only 3 times. It doubles the" ));
strcpy(line[LEFTSIDE][6], GetCatalogStr(li.li_Catalog, MSG_FAXI_3, "rider's movement factor." ));
leftlines = 7;
break;
case MAGICSHIRT:
strcpy(line[LEFTSIDE][4], GetCatalogStr(li.li_Catalog, MSG_SHIRT_1, "It adds +1 to the combat strength of the" ));
strcpy(line[LEFTSIDE][5], GetCatalogStr(li.li_Catalog, MSG_SHIRT_2, "wearer when he is defending. It also adds"));
strcpy(line[LEFTSIDE][6], GetCatalogStr(li.li_Catalog, MSG_SHIRT_3, "+1 to the movement factor of the wearer." ));
leftlines = 7;
break;
case MAILCOAT:
strcpy(line[LEFTSIDE][4], GetCatalogStr(li.li_Catalog, MSG_COAT_1, "It adds +2 to the combat strength of the" ));
strcpy(line[LEFTSIDE][5], GetCatalogStr(li.li_Catalog, MSG_COAT_2, "wearer, but only when the wearer is" ));
strcpy(line[LEFTSIDE][6], GetCatalogStr(li.li_Catalog, MSG_COAT_3, "defending." ));
leftlines = 7;
break;
case HEALINGPOTION:
strcpy(line[LEFTSIDE][4], GetCatalogStr(li.li_Catalog, MSG_POTION_1, "This treasure can be used only once. It" ));
strcpy(line[LEFTSIDE][5], GetCatalogStr(li.li_Catalog, MSG_POTION_2, "will heal any wounds that the hero is" ));
strcpy(line[LEFTSIDE][6], GetCatalogStr(li.li_Catalog, MSG_POTION_3, "suffering." ));
leftlines = 7;
break;
case TELEPORTSCROLL:
strcpy(line[LEFTSIDE][4], GetCatalogStr(li.li_Catalog, MSG_SCROLL_1, "This treasure can be used only once. It" ));
strcpy(line[LEFTSIDE][5], GetCatalogStr(li.li_Catalog, MSG_SCROLL_2, "will teleport the user to any desired" ));
strcpy(line[LEFTSIDE][6], GetCatalogStr(li.li_Catalog, MSG_SCROLL_3, "location." ));
leftlines = 7;
break;
default:
assert(0);
break;
}
rightlines = 0;
} elif (countertype == KINGDOM)
{ strcpy(line[LEFTSIDE][0], GetCatalogStr(li.li_Catalog, MSG_KINGDOM_NAME, "Kingdom Name"));
strcat(line[LEFTSIDE][0], ":");
pad(line[LEFTSIDE][0]);
strcat(line[LEFTSIDE][0], world[whichcounter].name);
strcpy(line[LEFTSIDE][1], GetCatalogStr(li.li_Catalog, MSG_KING, "King"));
strcat(line[LEFTSIDE][1], ":");
pad(line[LEFTSIDE][1]);
if (world[whichcounter].hero == -1)
{ strcat(line[LEFTSIDE][1], GetCatalogStr(li.li_Catalog, MSG_KING_NONE, "None"));
} else
{ strcat(line[LEFTSIDE][1], hero[world[whichcounter].hero].name);
}
strcpy(line[LEFTSIDE][2], GetCatalogStr(li.li_Catalog, MSG_TAXATION_FACTOR, "Taxation Factor"));
strcat(line[LEFTSIDE][2], ":");
pad(line[LEFTSIDE][2]);
stcl_d(numberstring, world[whichcounter].tax);
strcat(line[LEFTSIDE][2], numberstring);
strcpy(line[LEFTSIDE][3], GetCatalogStr(li.li_Catalog, MSG_TYPE, "Type"));
strcat(line[LEFTSIDE][3], ":");
pad(line[LEFTSIDE][3]);
if (world[whichcounter].type == LAND)
{ strcat(line[LEFTSIDE][3], GetCatalogStr(li.li_Catalog, MSG_LAND, "Land"));
} elif (world[whichcounter].type == ISLE)
{ strcat(line[LEFTSIDE][3], GetCatalogStr(li.li_Catalog, MSG_ISLAND, "Island"));
} elif (world[whichcounter].type == SEA)
{ strcat(line[LEFTSIDE][3], GetCatalogStr(li.li_Catalog, MSG_SEA, "Sea"));
} else
{ assert(world[whichcounter].type == PENINSULA);
strcat(line[LEFTSIDE][3], GetCatalogStr(li.li_Catalog, MSG_PENINSULA, "Peninsula"));
}
strcpy(line[LEFTSIDE][4], "Is (");
strcat(line[LEFTSIDE][4], GetCatalogStr(li.li_Catalog, MSG_ICE, "ice"));
strcat(line[LEFTSIDE][4], ")?");
pad(line[LEFTSIDE][4]);
if (world[whichcounter].is)
{ strcat(line[LEFTSIDE][4], GetCatalogStr(li.li_Catalog, MSG_YES, "Yes"));
} else
{ strcat(line[LEFTSIDE][4], GetCatalogStr(li.li_Catalog, MSG_NO, "No"));
}
leftlines = 5; // counting from 1
strcpy(line[RIGHTSIDE][0], GetCatalogStr(li.li_Catalog, MSG_CONTENTS, "Contents"));
strcat(line[RIGHTSIDE][0], ":");
whichline = oldwhichline = 1; // whichline always points to the NEXT line.
for (whichhero = 0; whichhero <= HEROES; whichhero++)
{ if (hero[whichhero].alive && hero[whichhero].where == whichcounter)
{ strcpy(line[RIGHTSIDE][whichline], " ");
strcat(line[RIGHTSIDE][whichline], GetCatalogStr(li.li_Catalog, MSG_HERO, "Hero"));
strcat(line[RIGHTSIDE][whichline], " ");
strcat(line[RIGHTSIDE][whichline], hero[whichhero].name);
strcat(line[RIGHTSIDE][whichline], " (");
stcl_d(numberstring, hero[whichhero].strength);
strcat(line[RIGHTSIDE][whichline], numberstring);
strcat(line[RIGHTSIDE][whichline], "-");
stcl_d(numberstring, hero[whichhero].moves);
strcat(line[RIGHTSIDE][whichline], numberstring);
strcat(line[RIGHTSIDE][whichline], ")");
whichline++;
} }
for (whichjarl = 0; whichjarl <= JARLS; whichjarl++)
{ if (jarl[whichjarl].alive && jarl[whichjarl].where == whichcounter)
{ strcpy(line[RIGHTSIDE][whichline], " ");
if (jarl[whichjarl].face == FACEUP)
{ strcat(line[RIGHTSIDE][whichline], GetCatalogStr(li.li_Catalog, MSG_JARL, "Jarl"));
strcat(line[RIGHTSIDE][whichline], " ");
strcat(line[RIGHTSIDE][whichline], jarl[whichjarl].name);
strcat(line[RIGHTSIDE][whichline], " (");
stcl_d(numberstring, jarl[whichjarl].strength);
strcat(line[RIGHTSIDE][whichline], numberstring);
strcat(line[RIGHTSIDE][whichline], "-");
stcl_d(numberstring, jarl[whichjarl].moves);
strcat(line[RIGHTSIDE][whichline], numberstring);
strcat(line[RIGHTSIDE][whichline], ")");
} else
{ strcat(line[RIGHTSIDE][whichline], GetCatalogStr(li.li_Catalog, MSG_UNKNOWN_JARL, "Unknown jarl"));
strcat(line[RIGHTSIDE][whichline], " (?-?)");
}
whichline++;
} }
for (whichmonster = 0; whichmonster <= MONSTERS; whichmonster++)
{ if (monster[whichmonster].alive && monster[whichmonster].where == whichcounter)
{ strcpy(line[RIGHTSIDE][whichline], " ");
strcat(line[RIGHTSIDE][whichline], monstertypes[monster[whichmonster].species]);
strcat(line[RIGHTSIDE][whichline], " ");
strcat(line[RIGHTSIDE][whichline], monster[whichmonster].name);
strcat(line[RIGHTSIDE][whichline], " (");
stcl_d(numberstring, monster[whichmonster].strength);
strcat(line[RIGHTSIDE][whichline], numberstring);
strcat(line[RIGHTSIDE][whichline], "-");
stcl_d(numberstring, monster[whichmonster].moves);
strcat(line[RIGHTSIDE][whichline], numberstring);
strcat(line[RIGHTSIDE][whichline], ")");
whichline++;
} }
for (whichtreasure = 0; whichtreasure <= TREASURES; whichtreasure++)
{ if
( treasure[whichtreasure].possessortype == KINGDOM
&& treasure[whichtreasure].where == whichcounter
)
{ strcpy(line[RIGHTSIDE][whichline], " ");
strcat(line[RIGHTSIDE][whichline], GetCatalogStr(li.li_Catalog, MSG_THE, "The"));
strcat(line[RIGHTSIDE][whichline], " ");
strcat(line[RIGHTSIDE][whichline], treasure[whichtreasure].name);
whichline++;
} }
for (whichsord = 0; whichsord <= SORDS; whichsord++)
{ if
( sord[whichsord].possessortype == KINGDOM
&& sord[whichsord].where == whichcounter
)
{ strcpy(line[RIGHTSIDE][whichline], " ");
strcat(line[RIGHTSIDE][whichline], GetCatalogStr(li.li_Catalog, MSG_SWORD, "Sword"));
strcat(line[RIGHTSIDE][whichline], " ");
strcat(line[RIGHTSIDE][whichline], sord[whichsord].name);
whichline++;
} }
if (whichline == oldwhichline)
{ strcpy(line[RIGHTSIDE][whichline], " ");
strcat(line[RIGHTSIDE][whichline], GetCatalogStr(li.li_Catalog, MSG_NONE, "None"));
whichline++;
}
rightlines = whichline;
} elif (countertype == SORD)
{ strcpy(line[LEFTSIDE][0], GetCatalogStr(li.li_Catalog, MSG_SWORD_NAME, "Sword Name"));
strcat(line[LEFTSIDE][0], ":");
pad(line[LEFTSIDE][0]);
strcat(line[LEFTSIDE][0], sord[whichcounter].name);
strcpy(line[LEFTSIDE][1], GetCatalogStr(li.li_Catalog, MSG_LOCATION, "Location"));
strcat(line[LEFTSIDE][1], ":");
pad(line[LEFTSIDE][1]);
strcat(line[LEFTSIDE][1], world[sord[whichcounter].where].name);
line[LEFTSIDE][2][0] = 0; // blank line
switch(whichcounter)
{
case BALMUNG:
strcpy(line[LEFTSIDE][3], GetCatalogStr(li.li_Catalog, MSG_BALMUNG_1, "In any fight where its wielder is" ));
strcpy(line[LEFTSIDE][4], GetCatalogStr(li.li_Catalog, MSG_BALMUNG_2, "attacking an enemy wearing magic armour," ));
strcpy(line[LEFTSIDE][5], GetCatalogStr(li.li_Catalog, MSG_BALMUNG_3, "it cancels out the benefit of the magic" ));
strcpy(line[LEFTSIDE][6], GetCatalogStr(li.li_Catalog, MSG_BALMUNG_4, "armour. Thus, the Mail Coat and the Magic"));
strcpy(line[LEFTSIDE][7], GetCatalogStr(li.li_Catalog, MSG_BALMUNG_5, "Shirt provide no protection against it." ));
leftlines = 8;
break;
case HRUNTING:
strcpy(line[LEFTSIDE][3], GetCatalogStr(li.li_Catalog, MSG_HRUNTING_1, "The other side must flee instead when the"));
strcpy(line[LEFTSIDE][4], GetCatalogStr(li.li_Catalog, MSG_HRUNTING_2, "combat result would be that the wielder's"));
strcpy(line[LEFTSIDE][5], GetCatalogStr(li.li_Catalog, MSG_HRUNTING_3, "side must flee." ));
leftlines = 6;
break;
case LOVI:
strcpy(line[LEFTSIDE][3], GetCatalogStr(li.li_Catalog, MSG_LOVI_1, "In any battle against a side including" ));
strcpy(line[LEFTSIDE][4], GetCatalogStr(li.li_Catalog, MSG_LOVI_2, "jarls, it adds an additional +2 to the" ));
strcpy(line[LEFTSIDE][5], GetCatalogStr(li.li_Catalog, MSG_LOVI_3, "wielder's combat factor." ));
leftlines = 6;
break;
default:
strcpy(line[LEFTSIDE][3], GetCatalogStr(li.li_Catalog, MSG_NO_SPECIAL_POWERS, "No special powers."));
leftlines = 4;
break;
}
rightlines = 0;
}
if (leftlines >= rightlines)
{ lines = leftlines;
} else
{ lines = rightlines;
}
if (rightlines > 0)
{ wide = 1;
} else
{ wide = 0;
}
if (!(InfoWindowPtr = (struct Window *) OpenWindowTags(NULL,
WA_Left, (SCREENXPIXEL / 2) - ((360 + (280 * wide )) / 2),
WA_Top, (SCREENYPIXEL / 2) - (( 30 + ( 10 * lines)) / 2),
WA_Width, 360 + (280 * wide ),
WA_Height, 30 + ( 10 * lines),
WA_IDCMP, IDCMP_CLOSEWINDOW | IDCMP_RAWKEY,
WA_Title, GetCatalogStr(li.li_Catalog, MSG_INFORMATION, "Information"),
WA_Gadgets, NULL,
WA_CustomScreen, ScreenPtr,
WA_DragBar, TRUE,
WA_CloseGadget, TRUE,
WA_NoCareRefresh, TRUE,
WA_Activate, TRUE,
WA_GimmeZeroZero, TRUE,
TAG_DONE)))
{ DisplayAlert(AT_Recovery, "\0\20\20Saga: Can't open information window!\0", 24);
cleanexit(EXIT_FAILURE);
}
fillwindow(InfoWindowPtr);
SetDrMd(InfoWindowPtr->RPort, JAM1);
if (countertype == HERO || countertype == JARL || countertype == MONSTER)
{ for (whichline = 0; whichline < leftlines; whichline++)
{ SetAPen(InfoWindowPtr->RPort, BLACK);
Move(InfoWindowPtr->RPort, 12 + 1, 13 + (whichline * 10) + 1);
Text(InfoWindowPtr->RPort, label[whichline], strlen(label[whichline]));
Move(InfoWindowPtr->RPort, 12 + (22 * 8) + 1, 13 + (whichline * 10) + 1);
Text(InfoWindowPtr->RPort, line[LEFTSIDE][whichline], strlen(line[LEFTSIDE][whichline]));
SetAPen(InfoWindowPtr->RPort, WHITE);
Move(InfoWindowPtr->RPort, 12, 13 + (whichline * 10));
Text(InfoWindowPtr->RPort, label[whichline], strlen(label[whichline]));
Move(InfoWindowPtr->RPort, 12 + (22 * 8), 13 + (whichline * 10));
Text(InfoWindowPtr->RPort, line[LEFTSIDE][whichline], strlen(line[LEFTSIDE][whichline]));
} }
else
{ for (whichline = 0; whichline < leftlines; whichline++)
{ SetAPen(InfoWindowPtr->RPort, BLACK);
Move(InfoWindowPtr->RPort, 12 + 1, 13 + (whichline * 10) + 1);
Text(InfoWindowPtr->RPort, line[LEFTSIDE][whichline], strlen(line[LEFTSIDE][whichline]));
SetAPen(InfoWindowPtr->RPort, WHITE);
Move(InfoWindowPtr->RPort, 12, 13 + (whichline * 10));
Text(InfoWindowPtr->RPort, line[LEFTSIDE][whichline], strlen(line[LEFTSIDE][whichline]));
} }
if (wide)
{ for (whichline = 0; whichline < rightlines; whichline++)
{ SetAPen(InfoWindowPtr->RPort, BLACK);
Move(InfoWindowPtr->RPort, 360 + 12 + 1, 13 + (whichline * 10) + 1);
Text(InfoWindowPtr->RPort, line[RIGHTSIDE][whichline], strlen(line[RIGHTSIDE][whichline]));
SetAPen(InfoWindowPtr->RPort, WHITE);
Move(InfoWindowPtr->RPort, 360 + 12, 13 + (whichline * 10));
Text(InfoWindowPtr->RPort, line[RIGHTSIDE][whichline], strlen(line[RIGHTSIDE][whichline]));
} }
if (counterrow)
{ info(countertype, whichcounter);
}
infoloop();
}
MODULE void flash(SLONG country)
{ SLONG colour;
if (country < 0 || country > 65)
{ return;
}
if (country == 9)
{ colour = 89; // Suder Gotland
} elif (country == 10)
{ colour = 90; // Juteland
} elif (country == 11)
{ colour = 91; // Scandia
} else
{ colour = country + 8;
}
SetRGB4(&ScreenPtr->ViewPort, colour, 15, 15, 15); // white flash
Delay(2); // hold the flash
if (country >= 36)
{ SetRGB4(&ScreenPtr->ViewPort, colour, 0, 0, 9); // dark blue
} elif (world[country].hero != -1)
{ SetRGB4
( &ScreenPtr->ViewPort,
colour,
herocolour[world[country].hero].red,
herocolour[world[country].hero].green,
herocolour[world[country].hero].blue
);
} elif (world[country].is)
{ SetRGB4(&ScreenPtr->ViewPort, colour, 12, 12, 12); // light grey ice
} else
{ SetRGB4
( &ScreenPtr->ViewPort,
colour,
taxcolours[world[country].tax].red,
taxcolours[world[country].tax].green,
taxcolours[world[country].tax].blue
);
} }
MODULE void summarywindow(void)
{ SLONG count,
i, j,
length,
linecolour[HEROES + 1],
lines = 0;
FLAG nomore = FALSE,
ok;
strcpy(line[0][0], GetCatalogStr(li.li_Catalog, MSG_SUMMARYLINE, "Hero Name C-M J K S T C S R Glry Luck $$$$"));
/* Hero Name C-M J K S T C S R Glry Luck $$$$
o o a i w r o t u
m v r n o e n a n
b e l g r a t t e
a m s d d s r u
t e o u o s
n m r l
t s e
s
Heldenname K-B J K S S K S @ Ruhm Glck $$$$
a e a ö c c o t @
m w r n h h n a @
p e l i w ä t t @
f g s g e t r u @
u r r z o s @
n e t e l
g i l
s c e
h
e */
for (i = 0; i <= HEROES; i++)
{ if (hero[i].control != NONE)
{ linecolour[lines] = 136 + i;
lines++;
strcpy(line[0][lines], hero[i].name);
length = strlen(hero[i].name);
for (j = length; j < 11; j++)
{ strcat(line[0][lines], " ");
}
stcl_d(numberstring, hero[i].strength);
strcat(line[0][lines], numberstring);
strcat(line[0][lines], "-");
stcl_d(numberstring, hero[i].moves);
strcat(line[0][lines], numberstring);
strcat(line[0][lines], " ");
count = 0;
for (j = 0; j <= JARLS; j++)
{ if (jarl[j].alive && jarl[j].hero == i)
{ count++;
} }
stcl_d(numberstring, count);
strcat(line[0][lines], numberstring);
strcat(line[0][lines], " ");
count = 0;
for (j = 0; j <= 35; j++)
{ if (world[j].hero == i)
{ count++;
} }
stcl_d(numberstring, count);
strcat(line[0][lines], numberstring);
strcat(line[0][lines], " ");
ok = FALSE;
for (j = 0; j <= SORDS; j++)
{ if
( sord[j].possessortype == HERO
&& sord[j].possessor == i
)
{ numberstring[0] = sord[j].name[0];
numberstring[1] = 0;
strcat(line[0][lines], numberstring);
ok = TRUE;
break;
} }
if (!ok)
{ strcat(line[0][lines], "-");
}
strcat(line[0][lines], " ");
count = 0;
for (j = 0; j <= TREASURES; j++)
{ if
( ( treasure[j].possessortype == HERO
&& treasure[j].possessor == i
)
|| ( treasure[j].possessortype == JARL
&& jarl[treasure[j].possessor].hero == i
) )
{ count++;
} }
stcl_d(numberstring, count);
strcat(line[0][lines], numberstring);
strcat(line[0][lines], " ");
if (hero[i].control == HUMAN)
{ strcat(line[0][lines], GetCatalogStr(li.li_Catalog, MSG_CHAR_HUMAN, "H"));
} else
{ assert(hero[i].control == AMIGA);
strcat(line[0][lines], "A");
}
strcat(line[0][lines], " ");
if (!hero[i].alive)
{ strcat(line[0][lines], GetCatalogStr(li.li_Catalog, MSG_CHAR_DEAD, "D"));
} elif (hero[i].wounded)
{ strcat(line[0][lines], GetCatalogStr(li.li_Catalog, MSG_CHAR_WOUNDED, "W"));
} else
{ strcat(line[0][lines], GetCatalogStr(li.li_Catalog, MSG_CHAR_HEALTHY, "H"));
}
strcat(line[0][lines], " ");
if (hero[i].rune == -1)
{ strcat(line[0][lines], "-");
} else
{ numberstring[0] = rune[hero[i].rune].name[0];
numberstring[1] = 0;
strcat(line[0][lines], numberstring);
}
stcl_d(numberstring, hero[i].glory);
length = strlen(numberstring);
for (j = length; j < 5; j++)
{ strcat(line[0][lines], " ");
}
strcat(line[0][lines], numberstring);
stcl_d(numberstring, hero[i].luck);
length = strlen(numberstring);
for (j = length; j < 5; j++)
{ strcat(line[0][lines], " ");
}
strcat(line[0][lines], numberstring);
count = hero[i].wealth;
for (j = 0; j <= JARLS; j++)
{ if (jarl[j].alive && jarl[j].hero == i)
{ count += jarl[j].wealth;
} }
stcl_d(numberstring, count);
length = strlen(numberstring);
for (j = length; j < 5; j++)
{ strcat(line[0][lines], " ");
}
strcat(line[0][lines], numberstring);
} }
line[0][++lines][0] = 0;
count = 0;
for (i = 0; i <= MONSTERS; i++)
{ if (!monster[i].taken)
{ count++;
} }
sprintf
( line[0][++lines], "%s:",
GetCatalogStr(li.li_Catalog, MSG_MONSTERS_IN_PILE, "Monsters in Pile")
);
pad(line[0][lines]);
stcl_d(numberstring, count);
strcat(line[0][lines], numberstring);
strcat(line[0][lines], " ");
strcat(line[0][lines], GetCatalogStr(li.li_Catalog, MSG_OF, "of"));
strcat(line[0][lines], " ");
stcl_d(numberstring, MONSTERS + 1);
strcat(line[0][lines], numberstring);
count = 0;
for (i = 0; i <= JARLS; i++)
{ if (!jarl[i].taken)
{ count++;
} }
sprintf
( line[0][++lines], "%s:",
GetCatalogStr(li.li_Catalog, MSG_JARLS_IN_PILE, "Jarls in Pile")
);
pad(line[0][lines]);
stcl_d(numberstring, count);
strcat(line[0][lines], numberstring);
strcat(line[0][lines], " ");
strcat(line[0][lines], GetCatalogStr(li.li_Catalog, MSG_OF, "of"));
strcat(line[0][lines], " ");
stcl_d(numberstring, JARLS + 1);
strcat(line[0][lines], numberstring);
count = 0;
for (i = 0; i <= TREASURES; i++)
{ if (!treasure[i].taken)
{ count++;
} }
sprintf
( line[0][++lines], "%s:",
GetCatalogStr(li.li_Catalog, MSG_TREASURES_IN_PILE, "Treasures in Pile")
);
pad(line[0][lines]);
stcl_d(numberstring, count);
strcat(line[0][lines], numberstring);
strcat(line[0][lines], " ");
strcat(line[0][lines], GetCatalogStr(li.li_Catalog, MSG_OF, "of"));
strcat(line[0][lines], " ");
stcl_d(numberstring, TREASURES + 1);
strcat(line[0][lines], numberstring);
if (!(InfoWindowPtr = (struct Window *) OpenWindowTags(NULL,
WA_Left, (SCREENXPIXEL / 2) - (SUMMARYWIDTH / 2),
WA_Top, (SCREENYPIXEL / 2) - ((SUMMARYHEIGHT + (lines * 10)) / 2),
WA_Width, SUMMARYWIDTH,
WA_Height, SUMMARYHEIGHT + (lines * 10),
WA_IDCMP, IDCMP_CLOSEWINDOW | IDCMP_RAWKEY,
WA_Title, GetCatalogStr(li.li_Catalog, MSG_GAME_SUMMARY, "Game Summary"),
WA_Gadgets, NULL,
WA_CustomScreen, ScreenPtr,
WA_DragBar, TRUE,
WA_CloseGadget, TRUE,
WA_NoCareRefresh, TRUE,
WA_Activate, TRUE,
WA_GimmeZeroZero, TRUE,
TAG_DONE)))
{ DisplayAlert(AT_Recovery, "\0\20\20Saga: Can't open summary window!\0", 24);
cleanexit(EXIT_FAILURE);
}
fillwindow(InfoWindowPtr);
SetDrMd(InfoWindowPtr->RPort, JAM1);
SetAPen(InfoWindowPtr->RPort, BLACK);
Move(InfoWindowPtr->RPort, 12 + 1, 13 + 1);
Text(InfoWindowPtr->RPort, line[0][0], strlen(line[0][0])); // headings
Move(InfoWindowPtr->RPort, 12 + 1, 16 + 1);
Draw(InfoWindowPtr->RPort, SUMMARYWIDTH - 20, 16 + 1); // underline
SetAPen(InfoWindowPtr->RPort, WHITE);
Move(InfoWindowPtr->RPort, 12, 13);
Text(InfoWindowPtr->RPort, line[0][0], strlen(line[0][0])); // headings
Move(InfoWindowPtr->RPort, 12, 16);
Draw(InfoWindowPtr->RPort, SUMMARYWIDTH - 20, 16); // underline
for (i = 1; i <= lines; i++)
{ SetAPen(InfoWindowPtr->RPort, BLACK);
Move(InfoWindowPtr->RPort, 12 + 1, 15 + (i * 10) + 1);
Text(InfoWindowPtr->RPort, line[0][i], strlen(line[0][i]));
if (DisplayDepth >= DEPTH && !nomore)
{ SetAPen(InfoWindowPtr->RPort, linecolour[i - 1]);
} else
{ SetAPen(InfoWindowPtr->RPort, WHITE);
}
Move(InfoWindowPtr->RPort, 12, 15 + (i * 10));
Text(InfoWindowPtr->RPort, line[0][i], strlen(line[0][i]));
if (line[0][i][0] == 0)
{ nomore = TRUE;
} }
infoloop();
}
EXPORT void screenoff(void)
{ if (dbuf)
{ if (!(ScreenBuf[1] = AllocScreenBuffer(ScreenPtr, NULL, SB_COPY_BITMAP)))
{ DisplayAlert(AT_Recovery, "\0\20\20Saga: Can't allocate alternate screen buffer!\0", 24);
cleanexit(EXIT_FAILURE);
}
WaitTOF();
while (!(ChangeScreenBuffer(ScreenPtr, ScreenBuf[1])));
} }
EXPORT void screenon(void)
{ WaitTOF();
if (dbuf)
{ while (!(ChangeScreenBuffer(ScreenPtr, ScreenBuf[0])));
FreeScreenBuffer(ScreenPtr, ScreenBuf[1]);
ScreenBuf[1] = NULL;
} }
EXPORT void hint(STRPTR thehint1, STRPTR thehint2)
{ TEXT thehint[19 + 1];
strcpy(thehint, thehint1);
strcat(thehint, "/");
strcat(thehint, thehint2);
SetAPen(MainWindowPtr->RPort, WHITE);
Move(MainWindowPtr->RPort, 640 - 4 - ((10 + strlen(thehint1)) * 8), MESSAGEY + 26);
Text(MainWindowPtr->RPort, thehint, strlen(thehint));
}
MODULE void cycle(SLONG whichhero, UWORD qual)
{ if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
{ if (hero[whichhero].control == 0)
{ hero[whichhero].control = 2;
} else
{ hero[whichhero].control--;
} }
else
{ if (hero[whichhero].control == 2)
{ hero[whichhero].control = 0;
} else
{ hero[whichhero].control++;
} }
GT_SetGadgetAttrs(CycleGadgetPtr[whichhero], MainWindowPtr, NULL, GTCY_Active, hero[whichhero].control, TAG_DONE);
}
MODULE void docwindow(SLONG number)
{ SLONG lines = 0, // to avoid spurious compiler warnings
whichline;
SWORD width, height;
switch (number)
{
case 1:
// runes
strcpy(line[0][0], rune[AMSIR].name);
strcat(line[0][0], ", ");
strcat(line[0][0], rune[AMSIR].desc);
strcpy(line[0][1], GetCatalogStr(li.li_Catalog, MSG_AMSIR_1, "A hero with this rune has twice the" ));
strcpy(line[0][2], GetCatalogStr(li.li_Catalog, MSG_AMSIR_2, "chance of having the gods notice him." ));
line[0][3][0] = 0;
strcpy(line[0][4], rune[EON].name);
strcat(line[0][4], ", ");
strcat(line[0][4], rune[EON].desc);
strcpy(line[0][5], GetCatalogStr(li.li_Catalog, MSG_EON_1, "+1 to movement factor." ));
line[0][6][0] = 0;
strcpy(line[0][7], rune[GEOFU].name);
strcat(line[0][7], ", ");
strcat(line[0][7], rune[GEOFU].desc);
strcpy(line[0][8], GetCatalogStr(li.li_Catalog, MSG_GEOFU_1, "A hero with this rune will have all the" ));
strcpy(line[0][9], GetCatalogStr(li.li_Catalog, MSG_GEOFU_2, "areas in his kingdom yield one additional"));
strcpy(line[0][10], GetCatalogStr(li.li_Catalog, MSG_GEOFU_3, "mark over and above the tax factor each" ));
strcpy(line[0][11], GetCatalogStr(li.li_Catalog, MSG_GEOFU_4, "turn." ));
line[0][12][0] = 0;
strcpy(line[0][13], rune[ING].name);
strcat(line[0][13], ", ");
strcat(line[0][13], rune[ING].desc);
strcpy(line[0][14], GetCatalogStr(li.li_Catalog, MSG_ING_1, "A hero with this rune can heal his wounds"));
strcpy(line[0][15], GetCatalogStr(li.li_Catalog, MSG_ING_2, "by spending one turn anywhere at rest." ));
line[0][16][0] = 0;
strcpy(line[0][17], rune[OGAL].name);
strcat(line[0][17], ", ");
strcat(line[0][17], rune[OGAL].desc);
strcpy(line[0][18], GetCatalogStr(li.li_Catalog, MSG_OGAL_1, "+1 to combat strength." ));
line[0][19][0] = 0;
strcpy(line[0][20], rune[SYGIL].name);
strcat(line[0][20], ", ");
strcat(line[0][20], rune[SYGIL].desc);
strcpy(line[0][21], GetCatalogStr(li.li_Catalog, MSG_SYGIL_1, "Every time a spell is cast at the hero" ));
strcpy(line[0][22], GetCatalogStr(li.li_Catalog, MSG_SYGIL_2, "who has this rune, it may not affect the" ));
strcpy(line[0][23], GetCatalogStr(li.li_Catalog, MSG_SYGIL_3, "hero (though it may affect those in the" ));
strcpy(line[0][24], GetCatalogStr(li.li_Catalog, MSG_SYGIL_4, "same area with him)." ));
lines = 25; // counting from 1
break;
case 2:
// spells
strcpy(line[0][0], "Hagall (");
strcat(line[0][0], GetCatalogStr(li.li_Catalog, MSG_HAIL, "hail" ));
strcat(line[0][0], ")");
strcpy(line[0][1], GetCatalogStr(li.li_Catalog, MSG_HAGALL_1, "Reduces the combat factor of each counter"));
strcpy(line[0][2], GetCatalogStr(li.li_Catalog, MSG_HAGALL_2, "in the area (including the caster) by one"));
strcpy(line[0][3], GetCatalogStr(li.li_Catalog, MSG_HAGALL_3, "for the rest of the turn. It also" ));
strcpy(line[0][4], GetCatalogStr(li.li_Catalog, MSG_HAGALL_4, "prevents any of the counters from moving" ));
strcpy(line[0][5], GetCatalogStr(li.li_Catalog, MSG_HAGALL_5, "by sea next turn." ));
line[0][6][0] = 0;
strcpy(line[0][7], "Is (");
strcat(line[0][7], GetCatalogStr(li.li_Catalog, MSG_ICE, "ice" ));
strcat(line[0][7], ")");
strcpy(line[0][8], GetCatalogStr(li.li_Catalog, MSG_IS_1, "Makes it impossible for any hero to" ));
strcpy(line[0][9], GetCatalogStr(li.li_Catalog, MSG_IS_2, "found, or continue to have a kingdom in" ));
strcpy(line[0][10], GetCatalogStr(li.li_Catalog, MSG_IS_3, "that country." ));
line[0][11][0] = 0;
strcpy(line[0][12], "Jara (");
strcat(line[0][12], GetCatalogStr(li.li_Catalog, MSG_LOSE_NEXT_TURN, "lose next turn" ));
strcat(line[0][12], ")");
strcpy(line[0][13], GetCatalogStr(li.li_Catalog, MSG_JARA_1, "All in the area lose their next turn." ));
line[0][14][0] = 0;
if (!(li.li_Catalog)) // only if running in English
{ strcpy(line[0][15], "Nied (");
strcat(line[0][15], GetCatalogStr(li.li_Catalog, MSG_N_R_A_L_N_T, "no result and lose next turn" ));
strcat(line[0][15], ")");
} else // German rune description text is too long
{ strcpy(line[0][15], "Nied");
}
strcpy(line[0][16], GetCatalogStr(li.li_Catalog, MSG_NIED_1, "Makes the combat result an automatic \"no"));
strcpy(line[0][17], GetCatalogStr(li.li_Catalog, MSG_NIED_2, "result\" and causes all in the area to" ));
strcpy(line[0][18], GetCatalogStr(li.li_Catalog, MSG_NIED_3, "lose one turn." ));
line[0][19][0] = 0;
strcpy(line[0][20], "Wynn (");
strcat(line[0][20], GetCatalogStr(li.li_Catalog, MSG_FLEEING, "fleeing" ));
strcat(line[0][20], ")");
strcpy(line[0][21], GetCatalogStr(li.li_Catalog, MSG_WYNN_1, "Forces all of the heroes and jarls in the"));
strcpy(line[0][22], GetCatalogStr(li.li_Catalog, MSG_WYNN_2, "area to flee." ));
line[0][23][0] = 0;
strcpy(line[0][24], "Yr (");
strcat(line[0][24], GetCatalogStr(li.li_Catalog, MSG_WOUNDING, "wounding" ));
strcat(line[0][24], ")");
strcpy(line[0][25], GetCatalogStr(li.li_Catalog, MSG_YR_1, "Causes all counters in the area (except" ));
strcpy(line[0][26], GetCatalogStr(li.li_Catalog, MSG_YR_2, "face down jarls or monster counters) to" ));
strcpy(line[0][27], GetCatalogStr(li.li_Catalog, MSG_YR_3, "be wounded." ));
lines = 28; // counting from 1
break;
case 3:
// swords
strcpy(line[0][0], sord[BALMUNG].name);
strcpy(line[0][1], GetCatalogStr(li.li_Catalog, MSG_BALMUNG_1, "In any fight where its wielder is" ));
strcpy(line[0][2], GetCatalogStr(li.li_Catalog, MSG_BALMUNG_2, "attacking an enemy wearing magic armour," ));
strcpy(line[0][3], GetCatalogStr(li.li_Catalog, MSG_BALMUNG_3, "it cancels out the benefit of the magic" ));
strcpy(line[0][4], GetCatalogStr(li.li_Catalog, MSG_BALMUNG_4, "armour. Thus, the Mail Coat and the Magic"));
strcpy(line[0][5], GetCatalogStr(li.li_Catalog, MSG_BALMUNG_5, "Shirt provide no protection against it." ));
line[0][6][0] = 0;
strcpy(line[0][7], sord[DRAGVENDILL].name);
strcpy(line[0][8], GetCatalogStr(li.li_Catalog, MSG_NO_SPECIAL_POWERS, "No special powers." ));
line[0][9][0] = 0;
strcpy(line[0][10], sord[GRAM].name);
strcpy(line[0][11], GetCatalogStr(li.li_Catalog, MSG_NO_SPECIAL_POWERS, "No special powers." ));
line[0][12][0] = 0;
strcpy(line[0][13], sord[HRUNTING].name);
strcpy(line[0][14], GetCatalogStr(li.li_Catalog, MSG_HRUNTING_1, "The other side must flee instead when the"));
strcpy(line[0][15], GetCatalogStr(li.li_Catalog, MSG_HRUNTING_2, "combat result would be that the wielder's"));
strcpy(line[0][16], GetCatalogStr(li.li_Catalog, MSG_HRUNTING_3, "side must flee." ));
line[0][17][0] = 0;
strcpy(line[0][18], sord[LOVI].name);
strcpy(line[0][19], GetCatalogStr(li.li_Catalog, MSG_LOVI_1, "In any battle against a side including" ));
strcpy(line[0][20], GetCatalogStr(li.li_Catalog, MSG_LOVI_2, "jarls, it adds an additional +2 to the" ));
strcpy(line[0][21], GetCatalogStr(li.li_Catalog, MSG_LOVI_3, "wielder's combat factor." ));
line[0][22][0] = 0;
strcpy(line[0][23], sord[TYRFING].name);
strcpy(line[0][24], GetCatalogStr(li.li_Catalog, MSG_NO_SPECIAL_POWERS, "No special powers." ));
lines = 25; // counting from 1
break;
case 4:
// treasures
strcpy(line[0][0], GetCatalogStr(li.li_Catalog, MSG_BROSUNG_NECKLACE, "Brosung Necklace" ));
strcpy(line[0][1], GetCatalogStr(li.li_Catalog, MSG_NECKLACE_1, "This treasure is worth 20 marks. It may" ));
strcpy(line[0][2], GetCatalogStr(li.li_Catalog, MSG_NECKLACE_2, "be traded for any item in a dragon's" ));
strcpy(line[0][3], GetCatalogStr(li.li_Catalog, MSG_NECKLACE_3, "hoard. The wearer moves into the area" ));
strcpy(line[0][4], GetCatalogStr(li.li_Catalog, MSG_NECKLACE_4, "adjacent to that of the dragon, and gives"));
strcpy(line[0][5], GetCatalogStr(li.li_Catalog, MSG_NECKLACE_5, "it to the dragon while taking what the" ));
strcpy(line[0][6], GetCatalogStr(li.li_Catalog, MSG_NECKLACE_6, "dragon had. The wearer may then see what" ));
strcpy(line[0][7], GetCatalogStr(li.li_Catalog, MSG_NECKLACE_7, "he had traded for." ));
line[0][8][0] = 0;
strcpy(line[0][9], "Frey Faxi" );
strcpy(line[0][10], GetCatalogStr(li.li_Catalog, MSG_FAXI_1, "This treasure is a magic horse that can" ));
strcpy(line[0][11], GetCatalogStr(li.li_Catalog, MSG_FAXI_2, "be ridden only 3 times. It doubles the" ));
strcpy(line[0][12], GetCatalogStr(li.li_Catalog, MSG_FAXI_3, "rider's movement factor." ));
line[0][13][0] = 0;
strcpy(line[0][14], GetCatalogStr(li.li_Catalog, MSG_MAGIC_SHIRT, "Magic Shirt" ));
strcpy(line[0][15], GetCatalogStr(li.li_Catalog, MSG_SHIRT_1, "It adds +1 to the combat strength of the" ));
strcpy(line[0][16], GetCatalogStr(li.li_Catalog, MSG_SHIRT_2, "wearer when he is defending. It also adds"));
strcpy(line[0][17], GetCatalogStr(li.li_Catalog, MSG_SHIRT_3, "+1 to the movement factor of the wearer." ));
line[0][18][0] = 0;
strcpy(line[0][19], GetCatalogStr(li.li_Catalog, MSG_MAIL_COAT, "Mail Coat" ));
strcpy(line[0][20], GetCatalogStr(li.li_Catalog, MSG_COAT_1, "It adds +2 to the combat strength of the" ));
strcpy(line[0][21], GetCatalogStr(li.li_Catalog, MSG_COAT_2, "wearer, but only when the wearer is" ));
strcpy(line[0][22], GetCatalogStr(li.li_Catalog, MSG_COAT_3, "defending." ));
if (advanced)
{ lines = 33; // counting from 1
line[0][23][0] = 0;
strcpy(line[0][24], GetCatalogStr(li.li_Catalog, MSG_HEALING_POTION, "Healing Potion" ));
strcpy(line[0][25], GetCatalogStr(li.li_Catalog, MSG_POTION_1, "This treasure can be used only once. It" ));
strcpy(line[0][26], GetCatalogStr(li.li_Catalog, MSG_POTION_2, "will heal any wounds that the hero is" ));
strcpy(line[0][27], GetCatalogStr(li.li_Catalog, MSG_POTION_3, "suffering." ));
line[0][28][0] = 0;
strcpy(line[0][29], GetCatalogStr(li.li_Catalog, MSG_TELEPORT_SCROLL, "Teleport Scroll" ));
strcpy(line[0][30], GetCatalogStr(li.li_Catalog, MSG_SCROLL_1, "This treasure can be used only once. It" ));
strcpy(line[0][31], GetCatalogStr(li.li_Catalog, MSG_SCROLL_2, "will teleport the user to any desired" ));
strcpy(line[0][32], GetCatalogStr(li.li_Catalog, MSG_SCROLL_3, "location." ));
} else
{ lines = 23;
}
break;
default:
assert(0);
break;
}
if (number == 1 || number == 2)
{ width = 364;
} else
{ assert(number == 3 || number == 4);
width = 400;
}
height = 30 + (10 * lines);
if (number == 3) // swords
{ height += 4; // because counter image overhangs
}
if (!(InfoWindowPtr = (struct Window *) OpenWindowTags(NULL,
WA_Left, (SCREENXPIXEL / 2) - (width / 2),
WA_Top, (SCREENYPIXEL / 2) - (height / 2),
WA_Width, width,
WA_Height, height,
WA_IDCMP, IDCMP_CLOSEWINDOW | IDCMP_RAWKEY,
WA_Title, GetCatalogStr(li.li_Catalog, MSG_INFORMATION, "Information"),
WA_Gadgets, NULL,
WA_CustomScreen, ScreenPtr,
WA_DragBar, TRUE,
WA_CloseGadget, TRUE,
WA_NoCareRefresh, TRUE,
WA_Activate, TRUE,
WA_GimmeZeroZero, TRUE,
TAG_DONE)))
{ DisplayAlert(AT_Recovery, "\0\20\20Saga: Can't open information window!\0", 24);
cleanexit(EXIT_FAILURE);
}
fillwindow(InfoWindowPtr);
SetAPen(InfoWindowPtr->RPort, BLACK);
SetDrMd(InfoWindowPtr->RPort, JAM1);
for (whichline = 0; whichline < lines; whichline++)
{ if
( whichline == 0
|| (number == 1 && (whichline == 4 || whichline == 7 || whichline == 13 || whichline == 17 || whichline == 20))
|| (number == 2 && (whichline == 7 || whichline == 12 || whichline == 15 || whichline == 20 || whichline == 24))
|| (number == 3 && (whichline == 7 || whichline == 10 || whichline == 13 || whichline == 18 || whichline == 23))
|| (number == 4 && (whichline == 9 || whichline == 14 || whichline == 19 || whichline == 24 || whichline == 29))
)
{ // embolden
SetSoftStyle(InfoWindowPtr->RPort, FSF_BOLD, FSF_BOLD);
} else
{ // debolden
SetSoftStyle(InfoWindowPtr->RPort, NULL, FSF_BOLD);
}
SetAPen(InfoWindowPtr->RPort, BLACK);
if (number == 3 || number == 4)
{ Move(InfoWindowPtr->RPort, 48 + 1, 13 + (whichline * 10) + 1);
} else
{ Move(InfoWindowPtr->RPort, 13 + 1, 13 + (whichline * 10) + 1);
}
Text(InfoWindowPtr->RPort, line[0][whichline], strlen(line[0][whichline]));
SetAPen(InfoWindowPtr->RPort, WHITE);
if (number == 3 || number == 4)
{ Move(InfoWindowPtr->RPort, 48, 13 + (whichline * 10));
} else
{ Move(InfoWindowPtr->RPort, 13, 13 + (whichline * 10));
}
Text(InfoWindowPtr->RPort, line[0][whichline], strlen(line[0][whichline]));
}
doc(number);
infoloop();
}
MODULE void infoloop(void)
{ FLAG done = FALSE;
ULONG class;
UWORD code, qual;
struct IntuiMessage* MsgPtr;
while(!done)
{ Wait(1L << InfoWindowPtr->UserPort->mp_SigBit);
while (MsgPtr = (struct IntuiMessage *) GetMsg(InfoWindowPtr->UserPort))
{ class = MsgPtr->Class;
code = MsgPtr->Code;
qual = MsgPtr->Qualifier;
ReplyMsg((struct Message *) MsgPtr);
switch(class)
{
case IDCMP_CLOSEWINDOW:
done = TRUE;
break;
case IDCMP_RAWKEY:
if (!(qual & IEQUALIFIER_REPEAT) && code < KEYUP && (code < FIRSTQUALIFIER || code > LASTQUALIFIER))
{ if
( code == ESCAPE
&& ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
)
{ cleanexit(EXIT_SUCCESS);
} else
{ done = TRUE;
} }
break;
default:
break;
} } }
CloseWindow(InfoWindowPtr);
InfoWindowPtr = NULL;
clearkybd();
}
#ifdef __STORM__
EXPORT int stcl_d(char* out, long lvalue)
{ ULONG calc,
i,
where;
FLAG started = FALSE;
if (lvalue < 0)
{ out[0] = '-';
where = 1;
lvalue = abs(lvalue);
} else
{ where = 0;
}
for (i = ONE_BILLION; i >= 1; i /= 10)
{ calc = lvalue / i;
assert(calc < 10);
if (calc || started || i == 1)
{ *(out + where) = (char) ('0' + calc);
where++;
started = TRUE;
}
lvalue %= i;
}
*(out + where) = 0;
return(where);
}
#endif